概要
上一章介紹了"二叉查找樹的相關理論知識,並通過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
二叉查找樹的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 }
關於二叉查找樹的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