二叉查找樹(二)之 C++的實現


 

概要

上一章介紹了"二叉查找樹的相關理論知識,並通過C語言實現了二叉查找樹"。這一章給出二叉查找樹的C++版本。這里不再對樹的相關概念進行介紹,若遇到不明白的概念,可以在上一章查找。

目錄
1. 二叉樹查找樹
2. 二叉查找樹的C++實現
3. 二叉查找樹的C++實現(完整源碼)
4. 二叉查找樹的C++測試程序

轉載請注明出處:http://www.cnblogs.com/skywang12345/p/3576373.html


更多內容: 數據結構與算法系列 目錄 

(01) 二叉查找樹(一)之 圖文解析 和 C語言的實現
(02) 二叉查找樹(二)之 C++的實現
(03) 二叉查找樹(三)之 Java的實現

 

二叉查找樹簡介

二叉查找樹(Binary Search Tree),又被稱為二叉搜索樹。
它是特殊的二叉樹:對於二叉樹,假設x為二叉樹中的任意一個結點,x節點包含關鍵字key,節點x的key值記為key[x]。如果y是x的左子樹中的一個結點,則key[y] <= key[x];如果y是x的右子樹的一個結點,則key[y] >= key[x]。那么,這棵樹就是二叉查找樹。如下圖所示:

在二叉查找樹中:
(01) 若任意節點的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
(02) 任意節點的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
(03) 任意節點的左、右子樹也分別為二叉查找樹。
(04) 沒有鍵值相等的節點(no duplicate nodes)。

 

二叉查找樹的C++實現

1. 節點和二叉查找樹的定義

1.1 二叉查找樹節點

template <class T>
class BSTNode{
    public:
        T key;            // 關鍵字(鍵值)
        BSTNode *left;    // 左孩子
        BSTNode *right;    // 右孩子
        BSTNode *parent;// 父結點

        BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):
            key(value),parent(),left(l),right(r) {}
};

BSTNode是二叉查找樹的節點,它包含二叉查找樹的幾個基本信息:
(01) key -- 它是關鍵字,是用來對二叉查找樹的節點進行排序的。
(02) left -- 它指向當前節點的左孩子。
(03) right -- 它指向當前節點的右孩子。
(04) parent -- 它指向當前節點的父結點。

 

1.2 二叉樹操作

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

    public:
        BSTree();
        ~BSTree();

        // 前序遍歷"二叉樹"
        void preOrder();
        // 中序遍歷"二叉樹"
        void inOrder();
        // 后序遍歷"二叉樹"
        void postOrder();

        // (遞歸實現)查找"二叉樹"中鍵值為key的節點
        BSTNode<T>* search(T key);
        // (非遞歸實現)查找"二叉樹"中鍵值為key的節點
        BSTNode<T>* iterativeSearch(T key);

        // 查找最小結點:返回最小結點的鍵值。
        T minimum();
        // 查找最大結點:返回最大結點的鍵值。
        T maximum();

        // 找結點(x)的后繼結點。即,查找"二叉樹中數據值大於該結點"的"最小結點"。
        BSTNode<T>* successor(BSTNode<T> *x);
        // 找結點(x)的前驅結點。即,查找"二叉樹中數據值小於該結點"的"最大結點"。
        BSTNode<T>* predecessor(BSTNode<T> *x);

        // 將結點(key為節點鍵值)插入到二叉樹中
        void insert(T key);

        // 刪除結點(key為節點鍵值)
        void remove(T key);

        // 銷毀二叉樹
        void destroy();

        // 打印二叉樹
        void print();
    private:
        // 前序遍歷"二叉樹"
        void preOrder(BSTNode<T>* tree) const;
        // 中序遍歷"二叉樹"
        void inOrder(BSTNode<T>* tree) const;
        // 后序遍歷"二叉樹"
        void postOrder(BSTNode<T>* tree) const;

        // (遞歸實現)查找"二叉樹x"中鍵值為key的節點
        BSTNode<T>* search(BSTNode<T>* x, T key) const;
        // (非遞歸實現)查找"二叉樹x"中鍵值為key的節點
        BSTNode<T>* iterativeSearch(BSTNode<T>* x, T key) const;

        // 查找最小結點:返回tree為根結點的二叉樹的最小結點。
        BSTNode<T>* minimum(BSTNode<T>* tree);
        // 查找最大結點:返回tree為根結點的二叉樹的最大結點。
        BSTNode<T>* maximum(BSTNode<T>* tree);

        // 將結點(z)插入到二叉樹(tree)中
        void insert(BSTNode<T>* &tree, BSTNode<T>* z);

        // 刪除二叉樹(tree)中的結點(z),並返回被刪除的結點
        BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z);

        // 銷毀二叉樹
        void destroy(BSTNode<T>* &tree);

        // 打印二叉樹
        void print(BSTNode<T>* tree, T key, int direction);
};

BSTree是二叉樹。它包含二叉查找樹的根節點和二叉查找樹的操作。二叉查找樹的操作中有許多重載函數,例如insert()函數,其中一個是內部接口,另一個是提供給外部的接口。

 

2 遍歷

這里講解前序遍歷、中序遍歷、后序遍歷3種方式。

2.1 前序遍歷
若二叉樹非空,則執行以下操作:
(01) 訪問根結點;
(02) 先序遍歷左子樹;
(03) 先序遍歷右子樹。

前序遍歷代碼

template <class T>
void BSTree<T>::preOrder(BSTNode<T>* tree) const
{
    if(tree != NULL)
    {
        cout<< tree->key << " " ;
        preOrder(tree->left);
        preOrder(tree->right);
    }
}

template <class T>
void BSTree<T>::preOrder() 
{
    preOrder(mRoot);
}

 

2.2 中序遍歷

若二叉樹非空,則執行以下操作:
(01) 中序遍歷左子樹;
(02) 訪問根結點;
(03) 中序遍歷右子樹。

中序遍歷代碼

template <class T>
void BSTree<T>::inOrder(BSTNode<T>* tree) const
{
    if(tree != NULL)
    {
        inOrder(tree->left);
        cout<< tree->key << " " ;
        inOrder(tree->right);
    }
}

template <class T>
void BSTree<T>::inOrder() 
{
    inOrder(mRoot);
}

 

2.3 后序遍歷

若二叉樹非空,則執行以下操作:
(01) 后序遍歷左子樹;
(02) 后序遍歷右子樹;
(03) 訪問根結點。

后序遍歷代碼

template <class T>
void BSTree<T>::postOrder(BSTNode<T>* tree) const
{
    if(tree != NULL)
    {
        postOrder(tree->left);
        postOrder(tree->right);
        cout<< tree->key << " " ;
    }
}

template <class T>
void BSTree<T>::postOrder() 
{
    postOrder(mRoot);
}

 

 

看看下面這顆樹的各種遍歷方式:

對於上面的二叉樹而言,
(01) 前序遍歷結果: 3 1 2 5 4 6
(02) 中序遍歷結果: 1 2 3 4 5 6 
(03) 后序遍歷結果: 2 1 4 6 5 3

 

3. 查找

遞歸版本的代碼

template <class T>
BSTNode<T>* BSTree<T>::search(BSTNode<T>* x, T key) const
{
    if (x==NULL || x->key==key)
        return x;

    if (key < x->key)
        return search(x->left, key);
    else
        return search(x->right, key);
}

template <class T>
BSTNode<T>* BSTree<T>::search(T key) 
{
    search(mRoot, key);
}

非遞歸版本的代碼

template <class T>
BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* x, T key) const
{
    while ((x!=NULL) && (x->key!=key))
    {
        if (key < x->key)
            x = x->left;
        else
            x = x->right;
    }

    return x;
}

template <class T>
BSTNode<T>* BSTree<T>::iterativeSearch(T key)
{
    iterativeSearch(mRoot, key);
}


4. 最大值和最小值

查找最大值的代碼

template <class T>
BSTNode<T>* BSTree<T>::maximum(BSTNode<T>* tree)
{
    if (tree == NULL)
        return NULL;

    while(tree->right != NULL)
        tree = tree->right;
    return tree;
}

template <class T>
T BSTree<T>::maximum()
{
    BSTNode<T> *p = maximum(mRoot);
    if (p != NULL)
        return p->key;

    return (T)NULL;
}

查找最小值的代碼

template <class T>
BSTNode<T>* BSTree<T>::minimum(BSTNode<T>* tree)
{
    if (tree == NULL)
        return NULL;

    while(tree->left != NULL)
        tree = tree->left;
    return tree;
}

template <class T>
T BSTree<T>::minimum()
{
    BSTNode<T> *p = minimum(mRoot);
    if (p != NULL)
        return p->key;

    return (T)NULL;
}

 

5. 前驅和后繼

節點的前驅:是該節點的左子樹中的最大節點。
節點的后繼:是該節點的右子樹中的最小節點。

查找前驅節點的代碼

/* 
 * 找結點(x)的前驅結點。即,查找"二叉樹中數據值小於該結點"的"最大結點"。
 */
template <class T>
BSTNode<T>* BSTree<T>::predecessor(BSTNode<T> *x)
{
    // 如果x存在左孩子,則"x的前驅結點"為 "以其左孩子為根的子樹的最大結點"。
    if (x->left != NULL)
        return maximum(x->left);

    // 如果x沒有左孩子。則x有以下兩種可能:
    // (01) x是"一個右孩子",則"x的前驅結點"為 "它的父結點"。
    // (01) x是"一個左孩子",則查找"x的最低的父結點,並且該父結點要具有右孩子",找到的這個"最低的父結點"就是"x的前驅結點"。
    BSTNode<T>* y = x->parent;
    while ((y!=NULL) && (x==y->left))
    {
        x = y;
        y = y->parent;
    }

    return y;
}

查找后繼節點的代碼

/* 
 * 找結點(x)的后繼結點。即,查找"二叉樹中數據值大於該結點"的"最小結點"。
 */
template <class T>
BSTNode<T>* BSTree<T>::successor(BSTNode<T> *x)
{
    // 如果x存在右孩子,則"x的后繼結點"為 "以其右孩子為根的子樹的最小結點"。
    if (x->right != NULL)
        return minimum(x->right);

    // 如果x沒有右孩子。則x有以下兩種可能:
    // (01) x是"一個左孩子",則"x的后繼結點"為 "它的父結點"。
    // (02) x是"一個右孩子",則查找"x的最低的父結點,並且該父結點要具有左孩子",找到的這個"最低的父結點"就是"x的后繼結點"。
    BSTNode<T>* y = x->parent;
    while ((y!=NULL) && (x==y->right))
    {
        x = y;
        y = y->parent;
    }

    return y;
}


6. 插入

插入節點的代碼

/* 
 * 將結點插入到二叉樹中
 *
 * 參數說明:
 *     tree 二叉樹的根結點
 *     z 插入的結點
 */
template <class T>
void BSTree<T>::insert(BSTNode<T>* &tree, BSTNode<T>* z)
{
    BSTNode<T> *y = NULL;
    BSTNode<T> *x = tree;

    // 查找z的插入位置
    while (x != NULL)
    {
        y = x;
        if (z->key < x->key)
            x = x->left;
        else
            x = x->right;
    }

    z->parent = y;
    if (y==NULL)
        tree = z;
    else if (z->key < y->key)
        y->left = z;
    else
        y->right = z;
}

/* 
 * 將結點(key為節點鍵值)插入到二叉樹中
 *
 * 參數說明:
 *     tree 二叉樹的根結點
 *     key 插入結點的鍵值
 */
template <class T>
void BSTree<T>::insert(T key)
{
    BSTNode<T> *z=NULL;

    // 如果新建結點失敗,則返回。
    if ((z=new BSTNode<T>(key,NULL,NULL,NULL)) == NULL)
        return ;

    insert(mRoot, z);
}

注:本文實現的二叉查找樹是允許插入相同鍵值的節點的。若想禁止二叉查找樹中插入相同鍵值的節點,可以參考"二叉查找樹(一)之 圖文解析 和 C語言的實現"中的插入函數進行修改。

 

7. 刪除

刪除節點的代碼

/* 
 * 刪除結點(z),並返回被刪除的結點
 *
 * 參數說明:
 *     tree 二叉樹的根結點
 *     z 刪除的結點
 */
template <class T>
BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z)
{
    BSTNode<T> *x=NULL;
    BSTNode<T> *y=NULL;

    if ((z->left == NULL) || (z->right == NULL) )
        y = z;
    else
        y = successor(z);

    if (y->left != NULL)
        x = y->left;
    else
        x = y->right;

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

    if (y->parent == NULL)
        tree = x;
    else if (y == y->parent->left)
        y->parent->left = x;
    else
        y->parent->right = x;

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

    return y;
}

/* 
 * 刪除結點(z),並返回被刪除的結點
 *
 * 參數說明:
 *     tree 二叉樹的根結點
 *     z 刪除的結點
 */
template <class T>
void BSTree<T>::remove(T key)
{
    BSTNode<T> *z, *node; 

    if ((z = search(mRoot, key)) != NULL)
        if ( (node = remove(mRoot, z)) != NULL)
            delete node;
}

 

8. 打印

打印二叉查找樹的代碼

/*
 * 打印"二叉查找樹"
 *
 * key        -- 節點的鍵值 
 * direction  --  0,表示該節點是根節點;
 *               -1,表示該節點是它的父結點的左孩子;
 *                1,表示該節點是它的父結點的右孩子。
 */
template <class T>
void BSTree<T>::print(BSTNode<T>* tree, T key, int direction)
{
    if(tree != NULL)
    {
        if(direction==0)    // tree是根節點
            cout << setw(2) << tree->key << " is root" << endl;
        else                // tree是分支節點
            cout << setw(2) << tree->key << " is " << setw(2) << key << "'s "  << setw(12) << (direction==1?"right child" : "left child") << endl;

        print(tree->left, tree->key, -1);
        print(tree->right,tree->key,  1);
    }
}

template <class T>
void BSTree<T>::print()
{
    if (mRoot != NULL)
        print(mRoot, mRoot->key, 0);
}

 

9. 銷毀

銷毀二叉查找樹的代碼

/*
 * 銷毀二叉樹
 */
template <class T>
void BSTree<T>::destroy(BSTNode<T>* &tree)
{
    if (tree==NULL)
        return ;

    if (tree->left != NULL)
        return destroy(tree->left);
    if (tree->right != NULL)
        return destroy(tree->right);

    delete tree;
    tree=NULL;
}

template <class T>
void BSTree<T>::destroy()
{
    destroy(mRoot);
}

 

二叉查找樹的C++實現(完整源碼)

二叉查找樹的C++實現文件(BSTree.h)

  1 /**
  2  * C++ 語言: 二叉查找樹
  3  *
  4  * @author skywang
  5  * @date 2013/11/07
  6  */
  7 
  8 #ifndef _BINARY_SEARCH_TREE_HPP_
  9 #define _BINARY_SEARCH_TREE_HPP_
 10 
 11 #include <iomanip>
 12 #include <iostream>
 13 using namespace std;
 14 
 15 template <class T>
 16 class BSTNode{
 17     public:
 18         T key;            // 關鍵字(鍵值)
 19         BSTNode *left;    // 左孩子
 20         BSTNode *right;    // 右孩子
 21         BSTNode *parent;// 父結點
 22 
 23         BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):
 24             key(value),parent(),left(l),right(r) {}
 25 };
 26 
 27 template <class T>
 28 class BSTree {
 29     private:
 30         BSTNode<T> *mRoot;    // 根結點
 31 
 32     public:
 33         BSTree();
 34         ~BSTree();
 35 
 36         // 前序遍歷"二叉樹"
 37         void preOrder();
 38         // 中序遍歷"二叉樹"
 39         void inOrder();
 40         // 后序遍歷"二叉樹"
 41         void postOrder();
 42 
 43         // (遞歸實現)查找"二叉樹"中鍵值為key的節點
 44         BSTNode<T>* search(T key);
 45         // (非遞歸實現)查找"二叉樹"中鍵值為key的節點
 46         BSTNode<T>* iterativeSearch(T key);
 47 
 48         // 查找最小結點:返回最小結點的鍵值。
 49         T minimum();
 50         // 查找最大結點:返回最大結點的鍵值。
 51         T maximum();
 52 
 53         // 找結點(x)的后繼結點。即,查找"二叉樹中數據值大於該結點"的"最小結點"。
 54         BSTNode<T>* successor(BSTNode<T> *x);
 55         // 找結點(x)的前驅結點。即,查找"二叉樹中數據值小於該結點"的"最大結點"。
 56         BSTNode<T>* predecessor(BSTNode<T> *x);
 57 
 58         // 將結點(key為節點鍵值)插入到二叉樹中
 59         void insert(T key);
 60 
 61         // 刪除結點(key為節點鍵值)
 62         void remove(T key);
 63 
 64         // 銷毀二叉樹
 65         void destroy();
 66 
 67         // 打印二叉樹
 68         void print();
 69     private:
 70         // 前序遍歷"二叉樹"
 71         void preOrder(BSTNode<T>* tree) const;
 72         // 中序遍歷"二叉樹"
 73         void inOrder(BSTNode<T>* tree) const;
 74         // 后序遍歷"二叉樹"
 75         void postOrder(BSTNode<T>* tree) const;
 76 
 77         // (遞歸實現)查找"二叉樹x"中鍵值為key的節點
 78         BSTNode<T>* search(BSTNode<T>* x, T key) const;
 79         // (非遞歸實現)查找"二叉樹x"中鍵值為key的節點
 80         BSTNode<T>* iterativeSearch(BSTNode<T>* x, T key) const;
 81 
 82         // 查找最小結點:返回tree為根結點的二叉樹的最小結點。
 83         BSTNode<T>* minimum(BSTNode<T>* tree);
 84         // 查找最大結點:返回tree為根結點的二叉樹的最大結點。
 85         BSTNode<T>* maximum(BSTNode<T>* tree);
 86 
 87         // 將結點(z)插入到二叉樹(tree)中
 88         void insert(BSTNode<T>* &tree, BSTNode<T>* z);
 89 
 90         // 刪除二叉樹(tree)中的結點(z),並返回被刪除的結點
 91         BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z);
 92 
 93         // 銷毀二叉樹
 94         void destroy(BSTNode<T>* &tree);
 95 
 96         // 打印二叉樹
 97         void print(BSTNode<T>* tree, T key, int direction);
 98 };
 99 
100 /* 
101  * 構造函數
102  */
103 template <class T>
104 BSTree<T>::BSTree():mRoot(NULL)
105 {
106 }
107 
108 /* 
109  * 析構函數
110  */
111 template <class T>
112 BSTree<T>::~BSTree() 
113 {
114     destroy();
115 }
116 
117 /*
118  * 前序遍歷"二叉樹"
119  */
120 template <class T>
121 void BSTree<T>::preOrder(BSTNode<T>* tree) const
122 {
123     if(tree != NULL)
124     {
125         cout<< tree->key << " " ;
126         preOrder(tree->left);
127         preOrder(tree->right);
128     }
129 }
130 
131 template <class T>
132 void BSTree<T>::preOrder() 
133 {
134     preOrder(mRoot);
135 }
136 
137 /*
138  * 中序遍歷"二叉樹"
139  */
140 template <class T>
141 void BSTree<T>::inOrder(BSTNode<T>* tree) const
142 {
143     if(tree != NULL)
144     {
145         inOrder(tree->left);
146         cout<< tree->key << " " ;
147         inOrder(tree->right);
148     }
149 }
150 
151 template <class T>
152 void BSTree<T>::inOrder() 
153 {
154     inOrder(mRoot);
155 }
156 
157 /*
158  * 后序遍歷"二叉樹"
159  */
160 template <class T>
161 void BSTree<T>::postOrder(BSTNode<T>* tree) const
162 {
163     if(tree != NULL)
164     {
165         postOrder(tree->left);
166         postOrder(tree->right);
167         cout<< tree->key << " " ;
168     }
169 }
170 
171 template <class T>
172 void BSTree<T>::postOrder() 
173 {
174     postOrder(mRoot);
175 }
176 
177 /*
178  * (遞歸實現)查找"二叉樹x"中鍵值為key的節點
179  */
180 template <class T>
181 BSTNode<T>* BSTree<T>::search(BSTNode<T>* x, T key) const
182 {
183     if (x==NULL || x->key==key)
184         return x;
185 
186     if (key < x->key)
187         return search(x->left, key);
188     else
189         return search(x->right, key);
190 }
191 
192 template <class T>
193 BSTNode<T>* BSTree<T>::search(T key) 
194 {
195     search(mRoot, key);
196 }
197 
198 /*
199  * (非遞歸實現)查找"二叉樹x"中鍵值為key的節點
200  */
201 template <class T>
202 BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* x, T key) const
203 {
204     while ((x!=NULL) && (x->key!=key))
205     {
206         if (key < x->key)
207             x = x->left;
208         else
209             x = x->right;
210     }
211 
212     return x;
213 }
214 
215 template <class T>
216 BSTNode<T>* BSTree<T>::iterativeSearch(T key)
217 {
218     iterativeSearch(mRoot, key);
219 }
220 
221 /* 
222  * 查找最小結點:返回tree為根結點的二叉樹的最小結點。
223  */
224 template <class T>
225 BSTNode<T>* BSTree<T>::minimum(BSTNode<T>* tree)
226 {
227     if (tree == NULL)
228         return NULL;
229 
230     while(tree->left != NULL)
231         tree = tree->left;
232     return tree;
233 }
234 
235 template <class T>
236 T BSTree<T>::minimum()
237 {
238     BSTNode<T> *p = minimum(mRoot);
239     if (p != NULL)
240         return p->key;
241 
242     return (T)NULL;
243 }
244  
245 /* 
246  * 查找最大結點:返回tree為根結點的二叉樹的最大結點。
247  */
248 template <class T>
249 BSTNode<T>* BSTree<T>::maximum(BSTNode<T>* tree)
250 {
251     if (tree == NULL)
252         return NULL;
253 
254     while(tree->right != NULL)
255         tree = tree->right;
256     return tree;
257 }
258 
259 template <class T>
260 T BSTree<T>::maximum()
261 {
262     BSTNode<T> *p = maximum(mRoot);
263     if (p != NULL)
264         return p->key;
265 
266     return (T)NULL;
267 }
268 
269 /* 
270  * 找結點(x)的后繼結點。即,查找"二叉樹中數據值大於該結點"的"最小結點"。
271  */
272 template <class T>
273 BSTNode<T>* BSTree<T>::successor(BSTNode<T> *x)
274 {
275     // 如果x存在右孩子,則"x的后繼結點"為 "以其右孩子為根的子樹的最小結點"。
276     if (x->right != NULL)
277         return minimum(x->right);
278 
279     // 如果x沒有右孩子。則x有以下兩種可能:
280     // (01) x是"一個左孩子",則"x的后繼結點"為 "它的父結點"。
281     // (02) x是"一個右孩子",則查找"x的最低的父結點,並且該父結點要具有左孩子",找到的這個"最低的父結點"就是"x的后繼結點"。
282     BSTNode<T>* y = x->parent;
283     while ((y!=NULL) && (x==y->right))
284     {
285         x = y;
286         y = y->parent;
287     }
288 
289     return y;
290 }
291  
292 /* 
293  * 找結點(x)的前驅結點。即,查找"二叉樹中數據值小於該結點"的"最大結點"。
294  */
295 template <class T>
296 BSTNode<T>* BSTree<T>::predecessor(BSTNode<T> *x)
297 {
298     // 如果x存在左孩子,則"x的前驅結點"為 "以其左孩子為根的子樹的最大結點"。
299     if (x->left != NULL)
300         return maximum(x->left);
301 
302     // 如果x沒有左孩子。則x有以下兩種可能:
303     // (01) x是"一個右孩子",則"x的前驅結點"為 "它的父結點"。
304     // (01) x是"一個左孩子",則查找"x的最低的父結點,並且該父結點要具有右孩子",找到的這個"最低的父結點"就是"x的前驅結點"。
305     BSTNode<T>* y = x->parent;
306     while ((y!=NULL) && (x==y->left))
307     {
308         x = y;
309         y = y->parent;
310     }
311 
312     return y;
313 }
314 
315 /* 
316  * 將結點插入到二叉樹中
317  *
318  * 參數說明:
319  *     tree 二叉樹的根結點
320  *     z 插入的結點
321  */
322 template <class T>
323 void BSTree<T>::insert(BSTNode<T>* &tree, BSTNode<T>* z)
324 {
325     BSTNode<T> *y = NULL;
326     BSTNode<T> *x = tree;
327 
328     // 查找z的插入位置
329     while (x != NULL)
330     {
331         y = x;
332         if (z->key < x->key)
333             x = x->left;
334         else
335             x = x->right;
336     }
337 
338     z->parent = y;
339     if (y==NULL)
340         tree = z;
341     else if (z->key < y->key)
342         y->left = z;
343     else
344         y->right = z;
345 }
346 
347 /* 
348  * 將結點(key為節點鍵值)插入到二叉樹中
349  *
350  * 參數說明:
351  *     tree 二叉樹的根結點
352  *     key 插入結點的鍵值
353  */
354 template <class T>
355 void BSTree<T>::insert(T key)
356 {
357     BSTNode<T> *z=NULL;
358 
359     // 如果新建結點失敗,則返回。
360     if ((z=new BSTNode<T>(key,NULL,NULL,NULL)) == NULL)
361         return ;
362 
363     insert(mRoot, z);
364 }
365 
366 /* 
367  * 刪除結點(z),並返回被刪除的結點
368  *
369  * 參數說明:
370  *     tree 二叉樹的根結點
371  *     z 刪除的結點
372  */
373 template <class T>
374 BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z)
375 {
376     BSTNode<T> *x=NULL;
377     BSTNode<T> *y=NULL;
378 
379     if ((z->left == NULL) || (z->right == NULL) )
380         y = z;
381     else
382         y = successor(z);
383 
384     if (y->left != NULL)
385         x = y->left;
386     else
387         x = y->right;
388 
389     if (x != NULL)
390         x->parent = y->parent;
391 
392     if (y->parent == NULL)
393         tree = x;
394     else if (y == y->parent->left)
395         y->parent->left = x;
396     else
397         y->parent->right = x;
398 
399     if (y != z) 
400         z->key = y->key;
401 
402     return y;
403 }
404 
405 /* 
406  * 刪除結點(z),並返回被刪除的結點
407  *
408  * 參數說明:
409  *     tree 二叉樹的根結點
410  *     z 刪除的結點
411  */
412 template <class T>
413 void BSTree<T>::remove(T key)
414 {
415     BSTNode<T> *z, *node; 
416 
417     if ((z = search(mRoot, key)) != NULL)
418         if ( (node = remove(mRoot, z)) != NULL)
419             delete node;
420 }
421 
422 /*
423  * 銷毀二叉樹
424  */
425 template <class T>
426 void BSTree<T>::destroy(BSTNode<T>* &tree)
427 {
428     if (tree==NULL)
429         return ;
430 
431     if (tree->left != NULL)
432         return destroy(tree->left);
433     if (tree->right != NULL)
434         return destroy(tree->right);
435 
436     delete tree;
437     tree=NULL;
438 }
439 
440 template <class T>
441 void BSTree<T>::destroy()
442 {
443     destroy(mRoot);
444 }
445 
446 /*
447  * 打印"二叉查找樹"
448  *
449  * key        -- 節點的鍵值 
450  * direction  --  0,表示該節點是根節點;
451  *               -1,表示該節點是它的父結點的左孩子;
452  *                1,表示該節點是它的父結點的右孩子。
453  */
454 template <class T>
455 void BSTree<T>::print(BSTNode<T>* tree, T key, int direction)
456 {
457     if(tree != NULL)
458     {
459         if(direction==0)    // tree是根節點
460             cout << setw(2) << tree->key << " is root" << endl;
461         else                // tree是分支節點
462             cout << setw(2) << tree->key << " is " << setw(2) << key << "'s "  << setw(12) << (direction==1?"right child" : "left child") << endl;
463 
464         print(tree->left, tree->key, -1);
465         print(tree->right,tree->key,  1);
466     }
467 }
468 
469 template <class T>
470 void BSTree<T>::print()
471 {
472     if (mRoot != NULL)
473         print(mRoot, mRoot->key, 0);
474 }
475 
476 #endif
View Code

二叉查找樹的C++測試程序(BSTreeTest.cpp)

 1 /**
 2  * C++ 語言: 二叉查找樹
 3  *
 4  * @author skywang
 5  * @date 2013/11/07
 6  */
 7 
 8 #include <iostream>
 9 #include "BSTree.h"
10 using namespace std;
11 
12 static int arr[]= {1,5,4,3,2,6};
13 #define TBL_SIZE(a) ( (sizeof(a)) / (sizeof(a[0])) )
14 
15 int main()
16 {
17     int i, ilen;
18     BSTree<int>* tree=new BSTree<int>();
19 
20     cout << "== 依次添加: ";
21     ilen = TBL_SIZE(arr);
22     for(i=0; i<ilen; i++) 
23     {
24         cout << arr[i] <<" ";
25         tree->insert(arr[i]);
26     }
27 
28     cout << "\n== 前序遍歷: ";
29     tree->preOrder();
30 
31     cout << "\n== 中序遍歷: ";
32     tree->inOrder();
33 
34     cout << "\n== 后序遍歷: ";
35     tree->postOrder();
36     cout << endl;
37 
38     cout << "== 最小值: " << tree->minimum() << endl;
39     cout << "== 最大值: " << tree->maximum() << endl;
40     cout << "== 樹的詳細信息: " << endl;
41     tree->print();
42 
43     cout << "\n== 刪除根節點: " << arr[3];
44     tree->remove(arr[3]);
45 
46     cout << "\n== 中序遍歷: ";
47     tree->inOrder();
48     cout << endl;
49 
50     // 銷毀二叉樹
51     tree->destroy();
52 
53     return 0;
54 }
View Code

關於二叉查找樹的C++實現有兩點需要補充說明的:
第1點:采用了STL模板。因此,二叉查找樹支持任意數據類型。
第2點:將二叉查找樹的"聲明"和"實現"都位於BSTree.h中。這是因為,在二叉查找樹的實現采用了模板;而C++編譯器不支持對模板的分離式編譯!

 

二叉查找樹的C++測試程序

上面的BSTreeTest.c是二叉查找樹樹的測試程序,運行結果如下:

== 依次添加: 1 5 4 3 2 6 
== 前序遍歷: 1 5 4 3 2 6 
== 中序遍歷: 1 2 3 4 5 6 
== 后序遍歷: 2 3 4 6 5 1 
== 最小值: 1
== 最大值: 6
== 樹的詳細信息: 
 1 is root
 5 is  1's  right child
 4 is  5's   left child
 3 is  4's   left child
 2 is  3's   left child
 6 is  5's  right child

== 刪除根節點: 3
== 中序遍歷: 1 2 4 5 6 

 

下面對測試程序的流程進行分析!

(01) 新建"二叉查找樹"root。


(02) 向二叉查找樹中依次插入1,5,4,3,2,6 。如下圖所示:

 

(03) 遍歷和查找
插入1,5,4,3,2,6之后,得到的二叉查找樹如下:

前序遍歷結果: 1 5 4 3 2 6
中序遍歷結果: 1 2 3 4 5 6
后序遍歷結果: 2 3 4 6 5 1
最小值是1,而最大值是6。

 

(04) 刪除節點4。如下圖所示:

 

(05) 重新遍歷該二叉查找樹。
中序遍歷結果: 1 2 4 5 6

 


免責聲明!

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



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