二叉查找樹 C++實現(含完整代碼)


       一般二叉樹的查找是通過遍歷整棵二叉樹實現,效率較低。二叉查找樹是一種特殊的二叉樹,可以提高查找的效率。二叉查找樹又稱為二叉排序樹或二叉搜索樹。

    二叉查找樹的定義

       二叉排序樹(Binary Search Tree)又稱二叉排序樹(Binary Sort Tree),或者是一顆空二叉樹,或者是具有一下特性的二叉樹:

  1.   若它的左子樹不為空,則左子樹上的所有結點的值均小於根節點的值。
  2.   若它的右子樹不為空,則右子樹上的所有結點的值均小於根節點的值。
  3.       它的左右子樹又分別是二叉排序樹。

  由定義可知,二叉查找樹中結點的值不允許重復。圖a是一棵二叉查找樹。當加入結點90后如圖b,圖b的二叉樹不是二叉查找樹,因其不滿足二叉排序樹的特性1.

                                           

     圖a                                                               圖b

   二叉樹的C++實現

  1. 二叉查找樹的結點結構
template<typename T>
//樹結點結構
class BSTNode{ public: T _key; //關鍵在字(鍵值)
    BSTNode *_lchild; //左孩
    BSTNode *_rchild; //右孩
    BSTNode *_parent; // 雙親 //構造函數
    BSTNode(T key ,BSTNode *lchild,BSTNode *rchild,BSTNode *parent): _key(key),_lchild(lchild),_rchild(rchild),_parent(parent){}; };

結點結構BSTNode中含有三個指針域,分別是:

  1. _lchild,指向結點的左孩子。
  2. _rchild,指向結點的右孩子。
  3. _parent,指向結點的雙親。

包含一個數據域 _key,為結點的關鍵字值。

使用構造函數初始化表列對以上四個數據進行初始化。

  2. 二叉查找樹的操作

 

template<typename T>
class BSTree{ private: BSTNode<T> *_Root ;  //根結點

public: BSTree():_Root(NULL){}; ~BSTree(){}; void insert (T key);//二叉樹的插入
 BSTNode<T>* search (T key)  ;//二叉樹的查找
    
    void preOrder()  ;  //先序輸出
    void inOrder() ;   //中序輸出
    void postOrder() ; //后序輸出
 BSTNode<T>* minimumNode();//查找最小的節點
    BSTNode<T>* maximumNode ();//查找最大的節點
 T minimumKey();//查找最小的鍵值
    T maximumKey();//查找最小的鍵值

    void print();//打印二叉樹
    void remove(T key); BSTNode<T>* predecessor(BSTNode<T>* x);//查找某個結點的前驅
    BSTNode<T>* sucessor(BSTNode<T>* x); //查找某個結點的后繼

    void destory (); //內部使用函數,供外部接口調用
private: void insert(BSTNode<T>* &tree,BSTNode<T>* z); BSTNode<T>* search(BSTNode<T>* &tree,T key) const; void preOrder(BSTNode<T>*&tree) const; void inOrder(BSTNode<T>*&tree) const; void postOrder(BSTNode<T>*&tree) const; BSTNode<T>* minimumNode(BSTNode<T> *&tree); BSTNode<T>* maximumNode (BSTNode<T> *&tree); void print(BSTNode<T>*& tree); BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z); void destory(BSTNode<T>*& tree); };

BSTree類包含了一個BSTNode指針數據成員,代表二叉查找樹的根結點。類種封裝了二叉查找樹常用的操作接口,包括:

  1. 插入操作:也是建立二叉查找樹的方法。
  2. 遍歷算法:包括前序、中序、后序(遞歸實現)。
  3. 查找操作:包括查找某個結點、查找最小結點、查找最大結點、查找最小值、查找最大值。
  4. 刪除操作。
  5. 銷毀操作。
  6. 打印操作:打印說明二叉樹的結構。

BSTree類大部分的函數都有兩個重載版本,一個僅供類內部使用(privata聲明),另一個則為類用戶使用的公用接口(public聲明)。

2.1二叉查找樹的遍歷

  2.1.1遍歷二叉樹

   遍歷二叉樹是指從根結點出發,按照某種次序訪問二叉樹所有結點,使得每個結點被且僅被訪問一次,這里的訪問可以是輸出、比較、更新、查看結點信息等各種操作。遍歷是二叉樹的一類重要操作,也是二叉樹的其他一些操作和各種應用算法的基本框架。用V表示根節點,用L表示左孩子,用R表示右孩子,且規定先L后R的訪問順序,則有VLR(前序)、LVR(中序)、LRV(后續)三種遍歷算法。對於圖a中的二叉樹,其遍歷結果為:

  

  前序遍歷:88 47 19 55 50 98

  中序遍歷:19 47 50 55 88 98 

  后序遍歷:19 50 55 47 98 88

下面來看BSTtree提供的三種遍歷接口:

  前序遍歷:

        1. 訪問根節點。
        2. 遍歷訪問左子樹。
        3. 遍歷訪問右子樹。
/* * *前序遍歷算法 *BSTree類內部調用函數 * */ template<typename T>
void BSTree<T>::preOrder(BSTNode<T>*&tree) const { if(tree) { cout<<tree->_key<<" "; preOrder(tree->_lchild); preOrder(tree->_rchild); } } /* *接口 * */template<typename T>
void BSTree<T>::postOrder() { postOrder(_Root); }
 

 

   

  中序遍歷:

      1. 遍歷訪問左子樹
      2. 訪問根節點。
      3. 遍歷訪問右子樹。

 

/* * *中序遍歷算法 *類內部調用函數 * */ template <typename T>
void BSTree<T>::inOrder(BSTNode<T>*&tree) const { if(tree) { inOrder(tree->_lchild); cout<<tree->_key<<" "; inOrder(tree->_rchild); } } /* * *接口 * */ template<typename T>
void BSTree<T>::inOrder() { inOrder(_Root); }

 

 后序遍歷:

      1. 遍歷訪問左子樹。
      2. 遍歷訪問右子樹。
      3. 訪問根節點。
/* * *后序遍歷算法 *類內部調用函數 * */ template <typename T>
void BSTree<T>::postOrder(BSTNode<T>*&tree) const { if(tree) { postOrder(tree->_lchild); postOrder(tree->_rchild); cout<<tree->_key<<" "; } } /* * *接口 * */ template<typename T>
void BSTree<T>::postOrder() { postOrder(_Root); }

 

  2.2二叉查找樹的插入

  構建查找二叉樹通過二叉查找樹的插入操作來進行。插入時嚴格按照查找二叉樹的定義來進行,其插入算法的基本過程可以分解為:

    1. 根結點為空則進行插入。
    2. 值比根結點小,在根結點的左子樹進行插入。
    3. 值比根結點大,在根節點的右子樹進行插入。

  本文采用非遞歸算法實現插入操作。

/* *插入操作 *非遞歸實現 *內部使用函數 */ template<typename T>
void BSTree<T> ::insert(BSTNode<T>* &tree,BSTNode<T>* z) { BSTNode<T>* parent = NULL; BSTNode<T>* temp = tree; //尋找插入點
    while(temp!=NULL) { parent= temp; if(z->_key>temp->_key) temp= temp->_rchild; else temp=temp->_lchild; } z->_parent = parent; if(parent==NULL) //如果樹本來就是空樹,則直接把z節點插入根節點
        tree = z; else if(z->_key>parent->_key) //如果z的值大於其雙親,則z為其雙親的右孩
        parent->_rchild = z; else parent->_lchild = z; } /* * *接口 */ template <typename T>
void BSTree<T>::insert(T key) { //創建一個新的節點,使用構造函數初始化
    BSTNode<T>* z= new BSTNode<T>(key,NULL,NULL,NULL); if(!z) //如果創建失敗則返回
        return ; //調用內部函數進行插入
 insert(_Root,z); } 

   2.3 二叉查找樹的查找

      2.3.1 查找某個值的結點

     這里提供遞歸與非遞歸算法實現查找操作。

/* *查找操作 *非遞歸實現 *內部使用函數 */ template <typename T> BSTNode<T>*  BSTree<T>::search(BSTNode<T>* &tree,T key) const { BSTNode<T>* temp = tree; while(temp != NULL) { if(temp->_key == key) return temp; else if(temp->_key>key) temp = temp->_lchild; else temp = temp->_rchild; } return NULL; } ////查找算法的遞歸實現
//template<typename T> //BSTNode<T>* BSTree<T>::search( BSTNode<T>* &tree,T key) const //{ // if(!tree) // { // if(tree->_key==key) // return tree; // if(tree->_key>key) // return search(tree->_lchild,key); // if(tree->_key<z->_key) // return search(tree->_rchild,key); // } // return NULL; //}

/* *接口 */ template <typename T> BSTNode<T> * BSTree<T>::search(T key) { return search(_Root,key); }

   2.3.2查找二叉查找樹值最小的結點

/* * *查找最小的結點 *內部調用函數 * */ template <typename T> BSTNode<T>* BSTree<T>::minimumNode(BSTNode<T>*&tree) { BSTNode<T>* temp = tree; while(temp->_lchild) { temp= temp->_lchild; } return temp; } /* *接口 */ template<typename T> BSTNode<T>* BSTree<T>::minimumNode() { return minimumNode(_Root); }

  2.3.3查找二叉查找樹中值最大的結點

/* * *查找鍵值最大的節點 *內部調用函數 *非遞歸實現 */ template<typename T> BSTNode<T>* BSTree<T>::maximumNode(BSTNode<T>* &tree) { BSTNode<T>* temp=tree; while(temp->_rchild) { temp= temp->_rchild; } return temp; } /* *接口 */ template<typename T> BSTNode<T>* BSTree<T>::maximumNode() { return maximumNode(_Root); }

   2.3.4查找二叉查找樹中最小的值

/* * *查找最小的鍵值 *外部接口函數 *調用內部函數minimumNode實現 */ template<typename T> T BSTree<T>::minimumKey() { BSTNode<T> *temp = minimumNode(_Root); return temp->_key; }

  2.4.5查找二叉查找樹中最大的值

/* * *查找最大的鍵值 *外部接口函數 *調用內部函數maximumKey */ template<typename T> T BSTree<T>::maximumKey() { BSTNode<T> *temp = maximumNode(_Root); return temp->_key; }

  2.3打印查找二叉樹

  該操作把二叉樹中每個結點的父結點、左右孩子結點的信息描述出來。

/*
*
*打印函數
*打印出平衡二叉樹
*BStree內部函數
*/
template<typename T>
void BSTree<T>::print(BSTNode<T>*& tree)
{
    if(tree) //如果tree不為空
    {
        if(tree->_lchild) //結點有左孩子
        {
            cout<<"節點"<<tree->_key<<"有左孩子為"<<tree->_lchild->_key<<endl;
        }
        else 
            cout<<"節點"<<tree->_key<<"無左孩子"<<endl;
        if(tree->_rchild)
        {
            cout<<"節點"<<tree->_key<<"有右孩子為"<<tree->_rchild->_key<<endl;
        }
        else 
            cout<<"節點"<<tree->_key<<"無右孩子"<<endl;
        print(tree->_lchild);
        print(tree->_rchild);
    }
}

/*
*接口
*/
template<typename T>
void BSTree<T>::print()
{
    print(_Root);
}

  2.4查找給定結點的前驅結點

/*
*查找某個節點x的前驅
*
*接口
*
*/

template <typename T>
BSTNode<T>* BSTree<T>::predecessor(BSTNode<T>* x)
{

    //如果x是最小的結點,則它沒有前驅
    if(x->_key == minimumNode(_Root)->_key)
        return NULL;
    
    //否則
    //先獲取二叉樹中鍵值與x的鍵值相同的結點y
    BSTNode <T> * y = NULL;
    y = search(_Root,x->_key);
    if(y==NULL) return NULL;

    //如果y有左孩子,則x的前驅為“以x的左孩為根的子樹的最大結點”
    if(y->_lchild!=NULL)
        return maximumNode(y->_lchild);

    //如果y沒有左孩子,則x有兩種可能:
    //1.y是一個右孩子,此時x的前驅為其雙親節點
    BSTNode<T>* parent = y->_parent;
    if(parent->_rchild == y)
        return parent;

    //2.y是一個左孩子,則其前驅為其雙親結點中“第一個擁有右孩子結點”的結點
    while(parent!=NULL&&parent->_rchild==NULL)
    {
        parent=parent->_parent;
    }
    return parent;
}

  2.5查找給定結點的后繼結點

/*
*查找某個節點x的后繼
*
*外部調用接口
*
*/
template <typename T>
BSTNode<T>* BSTree<T>::sucessor(BSTNode<T>* x)
{
    //如果x是鍵值最大的,則x沒有后繼結點
    if(x->_key==maximumNode(_Root)->_key)
        return NULL;

    //獲取x在二叉樹中的結點y
    BSTNode<T>* y  = NULL;
    y = search(_Root,x->_key);
    if(!y)              //若二叉樹沒有此結點
        return NULL;

    //如果y有右孩子,則y的后繼為其右孩子的最小結點
    if(y->_rchild!=NULL)
        return minimumNode(y->_rchild);

    //如果y沒有右孩子,則可分為兩種情況:
    //1.y 是左孩子。此時y的后繼為y的父結點
    BSTNode <T>* parent = y->_parent;
    if(y->_parent->_lchild == y)
        return parent;

    //2.y是右孩子。此時y的后繼結點為“第一個擁有左孩且不是y的直接雙親”的結點
    while(parent!=NULL)
    {
        if(parent->_lchild!=NULL&&parent!=y->_parent)
            return parent;
        parent=parent->_parent;
    }
    return NULL;
}

2.6 刪除結點

/*
*
*刪除結點
*BSTree類內部調用函數
*
*/
template <class T>
BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z)
{
    BSTNode<T> *x=NULL;
    BSTNode<T> *y=NULL;

    if ((z->_lchild == NULL) || (z->_rchild == NULL) )
        y = z;
    else
        y = sucessor(z);

    if (y->_lchild != NULL)
        x = y->_lchild;
    else
        x = y->_rchild;

    if (x != NULL)
        x->_parent = y->_parent;

    if (y->_parent == NULL)
        tree = x;
    else if (y == y->_parent->_lchild)
        y->_parent->_lchild = x;
    else
        y->_parent->_rchild= x;

    if (y != z) 
        z->_key = y->_key;

    return y;

}

/*
* 接口
*/
template<typename T>
void BSTree<T>::remove(T key)
{
    BSTNode<T> *z, *node; 
    if ((z = search(_Root, key)) != NULL)
        if ( (node = remove(_Root, z)) != NULL)
            delete node;
}

2.7銷毀二叉查找樹

/*
*
*銷毀查找二叉樹
*內部調用函數
*
*/
template<typename T>
void BSTree<T>::destory(BSTNode<T>*& tree)
{
    if(tree->_lchild!=NULL)
        destory(tree->_lchild);
    if(tree->_rchild!=NULL)
        destory(tree->_rchild);
    if(tree->_lchild==NULL&&tree->_rchild==NULL)
    {
        delete(tree);
        tree = NULL;
    }
}

/*
*接口
*/
template<typename T>
void BSTree<T>::destory()
{
    destory(_Root);
}
二叉查找樹的C++實現(完整源碼)

 

#ifndef _BINARY_SEARCH_TREE_
#define _BINARY_SEARCH_TREE_
#include <iostream>
using namespace std;
template<typename T>
//樹結點結構
class BSTNode{
public:
    T _key; //關鍵在字(鍵值)
    BSTNode *_lchild; //左孩
    BSTNode *_rchild; //右孩
    BSTNode *_parent; // 雙親
    
    //構造函數
    BSTNode(T key ,BSTNode *lchild,BSTNode *rchild,BSTNode *parent):
    _key(key),_lchild(lchild),_rchild(rchild),_parent(parent){};
};


template<typename T>
class BSTree{
private:
    BSTNode<T> *_Root ;  //根結點

public:
    BSTree():_Root(NULL){};
    ~BSTree(){};

    
    void insert (T key);//二叉樹的插入

    BSTNode<T>* search (T key)  ;//二叉樹的查找
    
    void preOrder()  ;  //先序輸出
    void inOrder() ;   //中序輸出
    void postOrder() ; //后序輸出

    BSTNode<T>* minimumNode();//查找最小的節點
    BSTNode<T>* maximumNode ();//查找最大的節點
    
    T minimumKey();//查找最小的鍵值
    T maximumKey();//查找最小的鍵值

    void print();//打印二叉樹
    void remove(T key);

    BSTNode<T>* predecessor(BSTNode<T>* x);//查找某個結點的前驅
    BSTNode<T>* sucessor(BSTNode<T>* x); //查找某個結點的后繼

    void destory ();

    //內部使用函數,供外部接口調用
private:
    void insert(BSTNode<T>* &tree,BSTNode<T>* z);
    BSTNode<T>* search(BSTNode<T>* &tree,T key) const;
    void preOrder(BSTNode<T>*&tree) const;
    void inOrder(BSTNode<T>*&tree) const;
    void postOrder(BSTNode<T>*&tree) const;
    BSTNode<T>* minimumNode(BSTNode<T> *&tree);
    BSTNode<T>* maximumNode (BSTNode<T> *&tree);
    void print(BSTNode<T>*& tree);
    BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z);
    void destory(BSTNode<T>*& tree);
};

/*
*插入操作
*非遞歸實現
*內部使用函數
*/
template<typename T>
void BSTree<T> ::insert(BSTNode<T>* &tree,BSTNode<T>* z)
{
    BSTNode<T>* parent = NULL;
    BSTNode<T>* temp = tree;

    //尋找插入點
    while(temp!=NULL)
    {
        parent= temp;
        if(z->_key>temp->_key)
            temp= temp->_rchild;
        else 
            temp=temp->_lchild;
    }
    z->_parent = parent;
    if(parent==NULL) //如果樹本來就是空樹,則直接把z節點插入根節點
        tree = z;
    else if(z->_key>parent->_key) //如果z的值大於其雙親,則z為其雙親的右孩
        parent->_rchild = z;
    else                          
        parent->_lchild = z;
}
/*
*
*接口
*/
template <typename T>
void BSTree<T>::insert(T key)
{
    //創建一個新的節點,使用構造函數初始化
    BSTNode<T>* z= new BSTNode<T>(key,NULL,NULL,NULL);
    if(!z) //如果創建失敗則返回
        return ;
    //調用內部函數進行插入
    insert(_Root,z);
}

/*
*查找操作
*非遞歸實現
*內部使用函數
*/
template <typename T>
BSTNode<T>*  BSTree<T>::search(BSTNode<T>* &tree,T key) const
{
    BSTNode<T>* temp = tree;
    while(temp != NULL)
    {
        if(temp->_key == key)
            return temp;
        else if(temp->_key>key)d
            temp = temp->_lchild;
        else
            temp = temp->_rchild;
    }
    return NULL;
}
////查找算法的遞歸實現
//template<typename T>
//BSTNode<T>* BSTree<T>::search( BSTNode<T>* &tree,T key) const
//{
//    if(!tree)
//    {
//        if(tree->_key==key)
//            return tree;
//        if(tree->_key>key)
//            return search(tree->_lchild,key);
//        if(tree->_key<z->_key)
//            return search(tree->_rchild,key);
//    }
//    return NULL;
//}

/*
*接口
*/
template <typename T>
BSTNode<T> * BSTree<T>::search(T key) 
{
    return search(_Root,key);
}
/*
*
*前序遍歷算法
*外部使用接口
*
*/
template<typename T>
void BSTree<T>::preOrder(BSTNode<T>*&tree) const
{
    if(tree)
    {
        cout<<tree->_key<<" ";
        preOrder(tree->_lchild);
        preOrder(tree->_rchild);
    }
}
template <typename T>
void BSTree<T>::inOrder(BSTNode<T>*&tree) const
{
    if(tree)
    {
        inOrder(tree->_lchild);
        cout<<tree->_key<<" ";
        inOrder(tree->_rchild);
    }
}
template <typename T>
void BSTree<T>::postOrder(BSTNode<T>*&tree) const
{
    if(tree)
    {
        postOrder(tree->_lchild);
        postOrder(tree->_rchild);
        cout<<tree->_key<<" ";
    }
}
/*
*遍歷算法
*分別為前序、中序、后序
*BSTree 類外部接口函數
*
*/
template<typename T>
void BSTree<T>::preOrder()
{
    preOrder(_Root);
}
template<typename T>
void BSTree<T>::inOrder()
{
    inOrder(_Root);
}
template<typename T>
void BSTree<T>::postOrder()
{
    postOrder(_Root);
}
/*
*
*查找最小的結點
*內部調用函數
*
*/
template <typename T>
BSTNode<T>* BSTree<T>::minimumNode(BSTNode<T>*&tree)
{
    BSTNode<T>* temp = tree;
    while(temp->_lchild)
    {
        temp= temp->_lchild;
    }
    return temp;
}

/*
*接口
*/
template<typename T>
BSTNode<T>* BSTree<T>::minimumNode()
{
    return minimumNode(_Root);
}
/*
*
*查找鍵值最大的節點
*內部調用函數
*非遞歸實現
*/
template<typename T>
BSTNode<T>* BSTree<T>::maximumNode(BSTNode<T>* &tree)
{
    BSTNode<T>* temp=tree;
    while(temp->_rchild)
    {er
        temp= temp->_rchild;
    }

    return temp;
}

/*
*接口
*/
template<typename T>
BSTNode<T>* BSTree<T>::maximumNode()
{
    return maximumNode(_Root);
}
/*
*
*查找最小的鍵值
*外部接口函數
*調用內部函數minimumNode實現
*/
template<typename T>
T BSTree<T>::minimumKey()
{
    BSTNode<T> *temp = minimumNode(_Root);
    return temp->_key;
}
/*
* 
*查找最大的鍵值
*外部接口函數
*調用內部函數maximumKey
*/
template<typename T>
T BSTree<T>::maximumKey()
{
    BSTNode<T> *temp = maximumNode(_Root);
    return temp->_key;
}

/*
*
*打印函數
*打印出平衡二叉樹
*BStree內部函數
*/
template<typename T>
void BSTree<T>::print(BSTNode<T>*& tree)
{
    if(tree) //如果tree不為空
    {
        if(tree->_lchild) //結點有左孩子
        {
            cout<<"節點"<<tree->_key<<"有左孩子為"<<tree->_lchild->_key<<endl;
        }
        else 
            cout<<"節點"<<tree->_key<<"無左孩子"<<endl;
        if(tree->_rchild)
        {
            cout<<"節點"<<tree->_key<<"有右孩子為"<<tree->_rchild->_key<<endl;
        }
        else 
            cout<<"節點"<<tree->_key<<"無右孩子"<<endl;
        print(tree->_lchild);
        print(tree->_rchild);
    }
}

/*
*接口
*/
template<typename T>
void BSTree<T>::print()
{
    print(_Root);
}
/*
*查找某個節點x的前驅
*
*外部函數調用
*
*/

template <typename T>
BSTNode<T>* BSTree<T>::predecessor(BSTNode<T>* x)
{

    //如果x是最小的結點,則它沒有前驅
    if(x->_key == minimumNode(_Root)->_key)
        return NULL;
    
    //否則
    //先獲取二叉樹中鍵值與x的鍵值相同的結點y
    BSTNode <T> * y = NULL;
    y = search(_Root,x->_key);
    if(y==NULL) return NULL;

    //如果y有左孩子,則x的前驅為“以x的左孩為根的子樹的最大結點”
    if(y->_lchild!=NULL)
        return maximumNode(y->_lchild);

    //如果y沒有左孩子,則x有兩種可能:
    //1.y是一個右孩子,此時x的前驅為其雙親節點
    BSTNode<T>* parent = y->_parent;
    if(parent->_rchild == y)
        return parent;

    //2.y是一個左孩子,則其前驅為其雙親結點中“第一個擁有右孩子結點”的結點
    while(parent!=NULL&&parent->_rchild==NULL)
    {
        parent=parent->_parent;
    }
    return parent;
}
/*
*查找某個節點x的后繼
*
*外部調用接口
*
*/
template <typename T>
BSTNode<T>* BSTree<T>::sucessor(BSTNode<T>* x)
{
    //如果x是鍵值最大的,則x沒有后繼結點
    if(x->_key==maximumNode(_Root)->_key)
        return NULL;

    //獲取x在二叉樹中的結點y
    BSTNode<T>* y  = NULL;
    y = search(_Root,x->_key);
    if(!y)              //若二叉樹沒有此結點
        return NULL;

    //如果y有右孩子,則y的后繼為其右孩子的最小結點
    if(y->_rchild!=NULL)
        return minimumNode(y->_rchild);

    //如果y沒有右孩子,則可分為兩種情況:
    //1.y 是左孩子。此時y的后繼為y的父結點
    BSTNode <T>* parent = y->_parent;
    if(y->_parent->_lchild == y)
        return parent;

    //2.y是右孩子。此時y的后繼結點為“第一個擁有左孩且不是y的直接雙親”的結點
    while(parent!=NULL)
    {
        if(parent->_lchild!=NULL&&parent!=y->_parent)
            return parent;
        parent=parent->_parent;
    }
    return NULL;
}
/*
*
*刪除結點
*BSTree類內部調用函數
*
*/
template <class T>
BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z)
{
    BSTNode<T> *x=NULL;
    BSTNode<T> *y=NULL;

    if ((z->_lchild == NULL) || (z->_rchild == NULL) )
        y = z;
    else
        y = sucessor(z);

    if (y->_lchild != NULL)
        x = y->_lchild;
    else
        x = y->_rchild;

    if (x != NULL)
        x->_parent = y->_parent;

    if (y->_parent == NULL)
        tree = x;
    else if (y == y->_parent->_lchild)
        y->_parent->_lchild = x;
    else
        y->_parent->_rchild= x;

    if (y != z) 
        z->_key = y->_key;

    return y;

}

/*
* 接口
*/
template<typename T>
void BSTree<T>::remove(T key)
{
    BSTNode<T> *z, *node; 
    if ((z = search(_Root, key)) != NULL)
        if ( (node = remove(_Root, z)) != NULL)
            delete node;
}
/*
*
*銷毀查找二叉樹
*內部調用函數
*
*/
template<typename T>
void BSTree<T>::destory(BSTNode<T>*& tree)
{
    if(tree->_lchild!=NULL)
        destory(tree->_lchild);
    if(tree->_rchild!=NULL)
        destory(tree->_rchild);
    if(tree->_lchild==NULL&&tree->_rchild==NULL)
    {
        delete(tree);
        tree = NULL;
    }
}

/*
*接口
*/
template<typename T>
void BSTree<T>::destory()
{
    destory(_Root);
}
#endif
BSTree.h
主函數 測試數據
// BSTree.cpp : 定義控制台應用程序的入口點。
#include "stdafx.h"
#include <iostream>
#include "BSTree.h"
using namespace std;
int main()
{
    BSTree<int> s ;
    int a ;
    cout<<"請輸入二叉樹結點以構造二叉查找樹:"<<endl;
    while(cin>>a )
        s.insert(a);
    cin.clear();

    cout<<"前序遍歷二叉查找樹:"<<endl;
    s.postOrder();
    cout<<endl;


    cout<<"中序遍歷二叉查找樹:"<<endl;
    s.inOrder();
    cout<<endl;


    cout<<"后序遍歷二叉查找樹:"<<endl;
    s.postOrder();
    cout<<endl;


    cout<<"打印二叉查找樹"<<endl;
    s.print();

    cout<<"請輸入要查找的數:"<<endl;

    while(cin>>a)
    {
        BSTNode<int>* findnode = s.search(a);
        if(!findnode)
        {
            cout<<"查找失敗"<<endl;
            s.insert(a);
            cout<<"已經將"<<a<<"插入二叉查找樹,現在二叉查找樹為:"<<endl;
            s.inOrder();
            cout<<endl;
        }
        else
        {
            cout<<findnode->_key<<"查找成功"<<endl;
        }
    }
    cin.clear();

    cout<<"請輸入結點以查找其前驅節點"<<endl;
    BSTNode<int>* findPreNode= new BSTNode<int>(1,NULL,NULL,NULL);
    while(cin>>findPreNode->_key)
    {
        BSTNode<int>* preNode ;
        if((preNode= s.predecessor(findPreNode))!=NULL)
        {
            cout<<"其前驅結點為:";
            cout<<preNode->_key<<endl;
        }
        else 
            cout<<"沒有前驅結點"<<endl;

        if((preNode= s.sucessor(findPreNode))!=NULL)
        {
            cout<<"其后繼結點為:";
            cout<<preNode->_key<<endl;
        }
        else 
            cout<<"沒有后繼結點"<<endl;
    }

    cin.clear();
    cout<<"請輸入要刪除的結點:"<<endl;
    while(cin >>a)
    {

        s.remove(a);
        cout<<"刪除后的二叉排序樹:"<<endl;
        s.inOrder();
    }


    BSTNode<int>* maxNode =  s.minimumNode();
    if(!maxNode)
        cout<<"最小的節點為:"<<maxNode->_key<<endl;

    BSTNode<int>* minNode = s.maximumNode();
    if(!minNode)
        cout<<"最大的節點為:"<<minNode->_key<<endl;

    cout<<"銷毀二叉樹"<<endl;
    s.destory();
    s.inOrder();

    system("pause");

    return 0;
}
View Code

運行結果:

 

 

=========================================================================================================================================完。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM