每日一數據結構封裝之二叉搜索樹

#include <iostream>
using namespace std;

template <typename T>
struct BSTNode
{
    T val;
    BSTNode<T>* lchild;
    BSTNode<T>* rchild;
    BSTNode<T>* parent;

    BSTNode(T t)
            : val(t), lchild(NULL), rchild(NULL){}

    BSTNode() = default;
};


template <typename T>
class BSTree
{
private:
    BSTNode<T>* root; //根節點
private:
    BSTNode<T>* search(BSTNode<T>* & p, T key);
    void remove(BSTNode<T>*  p, T key);
    void preOrder(BSTNode<T>* p);
    void inOrder(BSTNode<T>* p);
    void postOrder(BSTNode<T>* p);
    T search_min(BSTNode<T>* p);
    T search_max(BSTNode<T>* p);
    void destory(BSTNode<T>* &p);

public:
    BSTree();
    ~BSTree();

    void preOrder();
    void inOrder();
    void lastOrder();
    void layerOrder();

    BSTNode<T>* search1(T key);
    BSTNode<T>* search2(T key);

    T search_min();
    T search_max();

    BSTNode<T>* successor  (BSTNode<T>* x);
    BSTNode<T>* predecessor(BSTNode<T>* x);

    void insert(T key);
    void remove(T key);
    void destory();
    void print();
};


template <typename T>
BSTree<T>::BSTree() :root(NULL){};  //構造函數


template <typename T>
BSTree<T>::~BSTree()
{
    destory(root);
};

template <typename T>
void BSTree<T>::insert(T key)   //插入函數
{
    BSTNode<T>* par = NULL;
    BSTNode<T>* pnode = root;

    while (pnode != NULL)   //找到key應該插入的位置,並用par記錄其雙親
    {
        par = pnode;
        if (key > pnode->value)
            pnode = pnode->rchild;
        else if (key < pnode->value)
            pnode = pnode->lchild;
        else
            break;
    }

    pnode = new BSTNode<T>(key);      //創建新節點,插入到雙親節點相應的子節點
    if (par == NULL){
        root = pnode;
    }
    else{
        if (key > par->value){
            par->rchild = pnode;
        }
        else
            par->lchild = pnode;
    }
    pnode->parent = par;

};


template <typename T>
BSTNode<T>* BSTree<T>::search1(T key)   //迭代搜索
{
    BSTNode<T> * pnode = root;
    while (pnode != NULL)   //左右比較,依次往下進行
    {
        if (key == pnode->value)
            return pnode;
        if (key > pnode->value)
            pnode = pnode->rchild;
        else
            pnode = pnode->lchild;
    }
    return NULL;
};

template <typename T>
BSTNode<T>* BSTree<T>::search2(T key)   //遞歸搜索
{
    return search(root, key);
};


template <typename T>
BSTNode<T>* BSTree<T>::search(BSTNode<T>* & pnode, T key)    //遞歸搜索
{
    if (pnode == NULL)
        return NULL;
    if (pnode->value == key)
        return pnode;
    if (key > pnode->value)
        return search(pnode->rchild, key);
    return search(pnode->lchild, key);
};


template <typename T>
void BSTree<T>::remove(T key)   //刪除結點
{
    remove(root, key);
};

template <typename T>
void BSTree<T>::remove(BSTNode<T>* pnode, T key)    //刪除點有三種情況,討論如下
{
    if (pnode != NULL)
    {
        if (pnode->value == key)
        {
            BSTNode<T>* pdel=NULL;

            if (pnode->lchild == NULL || pnode->rchild == NULL)
                pdel = pnode;					//情況二、三:被刪節點只有左子樹或右子樹,或沒有孩子
            else
                pdel = predecessor(pnode);      //情況一:被刪節點同時有左右子樹,則刪除該節點的前驅

            BSTNode<T>* pchild=NULL;
            if (pdel->lchild != NULL)
                pchild = pdel->lchild;
            else
                pchild = pdel->rchild;

            if (pchild != NULL) //讓孩子指向被刪除節點的父節點
                pchild->parent = pdel->parent;

            if (pdel->parent == NULL)
                root = pchild;

            else if (pdel->parent->lchild==pdel)
            {
                pdel->parent->lchild = pchild;
            }
            else
            {
                pdel->parent->rchild = pchild;
            }

            if (pnode->value != pdel->value)
                pnode->value = pdel->value;
            delete pdel;
        }
            //進行遞歸刪除
        else if (key > pnode->value)
        {
            remove(pnode->rchild, key);
        }
        else remove(pnode->lchild, key);
    }
};

template <typename T>
BSTNode<T>* BSTree<T>::predecessor(BSTNode<T>* pnode)
{
    if (pnode->lchild != NULL)
    {
        pnode = pnode->lchild;
        while (pnode->rchild != NULL)
        {
            pnode = pnode->rchild;
        }
        return pnode;
    }

    BSTNode<T>* par = pnode->parent;
    while (par != NULL && par->lchild == pnode)
    {
        pnode = par;
        par = par->parent;
    }
    return par;
};

/*
 * 給定一棵二叉搜索樹中的一個結點,
 * 有時需要按中序遍歷的次序查找它的後繼。
 * 如果所有的關鍵字互不相同,
 * 則一個結點xx的後繼是大於x.key的最小關鍵字的結點。
 * 一棵二叉搜索樹的結構允許我們通過沒有任何關鍵字的比較來確定一個結點的後繼。
 * 如果後繼存在,SUCCESSOR過程將返回一棵二叉搜索樹中的結點xx的後繼;
 * 如果xx是這棵樹中的最大關鍵字元素,則返回null
 */
template <typename T>
BSTNode<T>* BSTree<T>::successor(BSTNode<T>* pnode)
{
    if (pnode->rchild != NULL)
    {
        pnode = pnode->rchild;
        while (pnode->lchild != NULL)
        {
            pnode = pnode->lchild;
        }
        return pnode;
    }

    BSTNode<T>* par = pnode->parent;
    while (par!=NULL&& par->rchild == pnode)
    {
        pnode = par;
        par = par->parent;
    }
    return par;
};



template <typename T>
void BSTree<T>::preOrder()
{
    preOrder(root);
};
template <typename T>
void BSTree<T>::preOrder(BSTNode<T> *p)
{
    if (p != NULL)
    {
        cout << p->value << endl;
        preOrder(p->lchild);
        preOrder(p->rchild);
    }
};
template <typename T>
void BSTree<T>::inOrder()
{
    inOrder(root);
};
template<typename T>
void BSTree<T>::inOrder(BSTNode<T>* p)
{
    if (p != NULL)
    {
        inOrder(p->lchild);
        cout << p->value << endl;
        inOrder(p->rchild);
    }
};

template <typename T>
void BSTree<T>::lastOrder()
{
    postOrder(root);
};
template <typename T>
void BSTree<T>::postOrder(BSTNode<T>* p)
{
    if (p != NULL)
    {
        postOrder(p->lchild);
        postOrder(p->rchild);
        cout << p->value<<endl;
    }
};
template <typename T>
T BSTree<T>::search_min()
{
    return search_min(root);
};
template <typename T>
T BSTree<T>::search_min(BSTNode<T>* p)
{
    if (p->lchild != NULL)
        return search_min(p->lchild);
    return p->value;
};


template <typename T>
T BSTree<T>::search_max()
{
    return search_max(root);
};
template <typename T>
T BSTree<T>::search_max(BSTNode<T>*p)
{
    if (p->rchild != NULL)
        return search_max(p->rchild);
    return p->value;
};

template<typename T>
void BSTree<T>::destory()
{
    destory(root);
};
template <typename T>
void BSTree<T>::destory(BSTNode<T>* &p)
{
    if (p != NULL)
    {
        if (p->lchild != NULL)
            destory(p->lchild);
        if (p->rchild != NULL)
            destory(p->rchild);
        delete p;
        p = NULL;
    }

};

 

發佈了36 篇原創文章 · 獲贊 15 · 訪問量 5939
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章