4树形结构二叉查找树
Posted long-w
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4树形结构二叉查找树相关的知识,希望对你有一定的参考价值。
一、二叉查找树简介
二叉查找树(Binary Search Tree),又被称为二叉搜索树。
它是特殊的二叉树:对于二叉树,假设x为二叉树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y]
<= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。那么,这棵树就是二叉查找树。
在二叉查找树中:
(1) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3) 任意节点的左、右子树也分别为二叉查找树。
(4) 没有键值相等的节点(no duplicate nodes)。
二、二叉查找树的C++实现
1. 节点和二叉查找树的定义
1.1 二叉查找树节点
1 template <class T> 2 class BSTNode{ 3 public: 4 T key; // 关键字(键值) 5 BSTNode *left; // 左孩子 6 BSTNode *right; // 右孩子 7 BSTNode *parent;// 父结点 8 9 BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r): 10 key(value),parent(),left(l),right(r) {} 11 };
BSTNode是二叉查找树的节点,它包含二叉查找树的几个基本信息:
(1) key -- 它是关键字,是用来对二叉查找树的节点进行排序的。
(2) left -- 它指向当前节点的左孩子。
(3) right -- 它指向当前节点的右孩子。
(4) parent -- 它指向当前节点的父结点。
1.2 二叉树操作
1 template <class T> 2 class BSTree { 3 private: 4 BSTNode<T> *mRoot; // 根结点 5 6 public: 7 BSTree(); 8 ~BSTree(); 9 10 // 前序遍历"二叉树" 11 void preOrder(); 12 // 中序遍历"二叉树" 13 void inOrder(); 14 // 后序遍历"二叉树" 15 void postOrder(); 16 17 // (递归实现)查找"二叉树"中键值为key的节点 18 BSTNode<T>* search(T key); 19 // (非递归实现)查找"二叉树"中键值为key的节点 20 BSTNode<T>* iterativeSearch(T key); 21 22 // 查找最小结点:返回最小结点的键值。 23 T minimum(); 24 // 查找最大结点:返回最大结点的键值。 25 T maximum(); 26 27 // 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。 28 BSTNode<T>* successor(BSTNode<T> *x); 29 // 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。 30 BSTNode<T>* predecessor(BSTNode<T> *x); 31 32 // 将结点(key为节点键值)插入到二叉树中 33 void insert(T key); 34 35 // 删除结点(key为节点键值) 36 void remove(T key); 37 38 // 销毁二叉树 39 void destroy(); 40 41 // 打印二叉树 42 void print(); 43 private: 44 // 前序遍历"二叉树" 45 void preOrder(BSTNode<T>* tree) const; 46 // 中序遍历"二叉树" 47 void inOrder(BSTNode<T>* tree) const; 48 // 后序遍历"二叉树" 49 void postOrder(BSTNode<T>* tree) const; 50 51 // (递归实现)查找"二叉树x"中键值为key的节点 52 BSTNode<T>* search(BSTNode<T>* x, T key) const; 53 // (非递归实现)查找"二叉树x"中键值为key的节点 54 BSTNode<T>* iterativeSearch(BSTNode<T>* x, T key) const; 55 56 // 查找最小结点:返回tree为根结点的二叉树的最小结点。 57 BSTNode<T>* minimum(BSTNode<T>* tree); 58 // 查找最大结点:返回tree为根结点的二叉树的最大结点。 59 BSTNode<T>* maximum(BSTNode<T>* tree); 60 61 // 将结点(z)插入到二叉树(tree)中 62 void insert(BSTNode<T>* &tree, BSTNode<T>* z); 63 64 // 删除二叉树(tree)中的结点(z),并返回被删除的结点 65 BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z); 66 67 // 销毁二叉树 68 void destroy(BSTNode<T>* &tree); 69 70 // 打印二叉树 71 void print(BSTNode<T>* tree, T key, int direction); 72 };
BSTree是二叉树。它包含二叉查找树的根节点和二叉查找树的操作。二叉查找树的操作中有许多重载函数,例如insert()函数,其中一个是内部接口,另一个是提供给外部的接口。
2 遍历
这里讲解前序遍历、中序遍历、后序遍历3种方式。
2.1 前序遍历
若二叉树非空,则执行以下操作:
(1) 访问根结点;
(2) 先序遍历左子树;
(3) 先序遍历右子树。
前序遍历代码
1 template <class T> 2 void BSTree<T>::preOrder(BSTNode<T>* tree) const 3 { 4 if(tree != NULL) 5 { 6 cout<< tree->key << " " ; 7 preOrder(tree->left); 8 preOrder(tree->right); 9 } 10 } 11 12 template <class T> 13 void BSTree<T>::preOrder() 14 { 15 preOrder(mRoot); 16 }
2.2 中序遍历
若二叉树非空,则执行以下操作:
(1) 中序遍历左子树;
(2) 访问根结点;
(3) 中序遍历右子树。
中序遍历代码
1 template <class T> 2 void BSTree<T>::inOrder(BSTNode<T>* tree) const 3 { 4 if(tree != NULL) 5 { 6 inOrder(tree->left); 7 cout<< tree->key << " " ; 8 inOrder(tree->right); 9 } 10 } 11 12 template <class T> 13 void BSTree<T>::inOrder() 14 { 15 inOrder(mRoot); 16 }
2.3 后序遍历
若二叉树非空,则执行以下操作:
(1) 后序遍历左子树;
(2) 后序遍历右子树;
(3) 访问根结点。
后序遍历代码
1 template <class T> 2 void BSTree<T>::postOrder(BSTNode<T>* tree) const 3 { 4 if(tree != NULL) 5 { 6 postOrder(tree->left); 7 postOrder(tree->right); 8 cout<< tree->key << " " ; 9 } 10 } 11 12 template <class T> 13 void BSTree<T>::postOrder() 14 { 15 postOrder(mRoot); 16 }
前驱和后继
节点的前驱:是该节点的左子树中的最大节点。
节点的后继:是该节点的右子树中的最小节点。
【完整示例】
BSTree.h
1 #ifndef _BINARY_SEARCH_TREE_HPP_ 2 #define _BINARY_SEARCH_TREE_HPP_ 3 4 #include <iomanip> 5 #include <iostream> 6 using namespace std; 7 8 template <class T> 9 class BSTNode{ 10 public: 11 T key; // 关键字(键值) 12 BSTNode *left; // 左孩子 13 BSTNode *right; // 右孩子 14 BSTNode *parent;// 父结点 15 16 BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r): 17 key(value),parent(),left(l),right(r) {} 18 }; 19 20 template <class T> 21 class BSTree { 22 private: 23 BSTNode<T> *mRoot; // 根结点 24 25 public: 26 BSTree(); 27 ~BSTree(); 28 29 // 前序遍历"二叉树" 30 void preOrder(); 31 // 中序遍历"二叉树" 32 void inOrder(); 33 // 后序遍历"二叉树" 34 void postOrder(); 35 36 // (递归实现)查找"二叉树"中键值为key的节点 37 BSTNode<T>* search(T key); 38 // (非递归实现)查找"二叉树"中键值为key的节点 39 BSTNode<T>* iterativeSearch(T key); 40 41 // 查找最小结点:返回最小结点的键值。 42 T minimum(); 43 // 查找最大结点:返回最大结点的键值。 44 T maximum(); 45 46 // 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。 47 BSTNode<T>* successor(BSTNode<T> *x); 48 // 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。 49 BSTNode<T>* predecessor(BSTNode<T> *x); 50 51 // 将结点(key为节点键值)插入到二叉树中 52 void insert(T key); 53 54 // 删除结点(key为节点键值) 55 void remove(T key); 56 57 // 销毁二叉树 58 void destroy(); 59 60 // 打印二叉树 61 void print(); 62 private: 63 // 前序遍历"二叉树" 64 void preOrder(BSTNode<T>* tree) const; 65 // 中序遍历"二叉树" 66 void inOrder(BSTNode<T>* tree) const; 67 // 后序遍历"二叉树" 68 void postOrder(BSTNode<T>* tree) const; 69 70 // (递归实现)查找"二叉树x"中键值为key的节点 71 BSTNode<T>* search(BSTNode<T>* x, T key) const; 72 // (非递归实现)查找"二叉树x"中键值为key的节点 73 BSTNode<T>* iterativeSearch(BSTNode<T>* x, T key) const; 74 75 // 查找最小结点:返回tree为根结点的二叉树的最小结点。 76 BSTNode<T>* minimum(BSTNode<T>* tree); 77 // 查找最大结点:返回tree为根结点的二叉树的最大结点。 78 BSTNode<T>* maximum(BSTNode<T>* tree); 79 80 // 将结点(z)插入到二叉树(tree)中 81 void insert(BSTNode<T>* &tree, BSTNode<T>* z); 82 83 // 删除二叉树(tree)中的结点(z),并返回被删除的结点 84 BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z); 85 86 // 销毁二叉树 87 void destroy(BSTNode<T>* &tree); 88 89 // 打印二叉树 90 void print(BSTNode<T>* tree, T key, int direction); 91 }; 92 93 /* 94 * 构造函数 95 */ 96 template <class T> 97 BSTree<T>::BSTree():mRoot(NULL) 98 { 99 } 100 101 /* 102 * 析构函数 103 */ 104 template <class T> 105 BSTree<T>::~BSTree() 106 { 107 destroy(); 108 } 109 110 /* 111 * 前序遍历"二叉树" 112 */ 113 template <class T> 114 void BSTree<T>::preOrder(BSTNode<T>* tree) const 115 { 116 if(tree != NULL) 117 { 118 cout<< tree->key << " " ; 119 preOrder(tree->left); 120 preOrder(tree->right); 121 } 122 } 123 124 template <class T> 125 void BSTree<T>::preOrder() 126 { 127 preOrder(mRoot); 128 } 129 130 /* 131 * 中序遍历"二叉树" 132 */ 133 template <class T> 134 void BSTree<T>::inOrder(BSTNode<T>* tree) const 135 { 136 if(tree != NULL) 137 { 138 inOrder(tree->left); 139 cout<< tree->key << " " ; 140 inOrder(tree->right); 141 } 142 } 143 144 template <class T> 145 void BSTree<T>::inOrder() 146 { 147 inOrder(mRoot); 148 } 149 150 /* 151 * 后序遍历"二叉树" 152 */ 153 template <class T> 154 void BSTree<T>::postOrder(BSTNode<T>* tree) const 155 { 156 if(tree != NULL) 157 { 158 postOrder(tree->left); 159 postOrder(tree->right); 160 cout<< tree->key << " " ; 161 } 162 } 163 164 template <class T> 165 void BSTree<T>::postOrder() 166 { 167 postOrder(mRoot); 168 } 169 170 /* 171 * (递归实现)查找"二叉树x"中键值为key的节点 172 */ 173 template <class T> 174 BSTNode<T>* BSTree<T>::search(BSTNode<T>* x, T key) const 175 { 176 if (x==NULL || x->key==key) 177 return x; 178 179 if (key < x->key) 180 return search(x->left, key); 181 else 182 return search(x->right, key); 183 } 184 185 template <class T> 186 BSTNode<T>* BSTree<T>::search(T key) 187 { 188 search(mRoot, key); 189 } 190 191 /* 192 * (非递归实现)查找"二叉树x"中键值为key的节点 193 */ 194 template <class T> 195 BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* x, T key) const 196 { 197 while ((x!=NULL) && (x->key!=key)) 198 { 199 if (key < x->key) 200 x = x->left; 201 else 202 x = x->right; 203 } 204 205 return x; 206 } 207 208 template <class T> 209 BSTNode<T>* BSTree<T>::iterativeSearch(T key) 210 { 211 iterativeSearch(mRoot, key); 212 } 213 214 /* 215 * 查找最小结点:返回tree为根结点的二叉树的最小结点。 216 */ 217 template <class T> 218 BSTNode<T>* BSTree<T>::minimum(BSTNode<T>* tree) 219 { 220 if (tree == NULL) 221 return NULL; 222 223 while(tree->left != NULL) 224 tree = tree->left; 225 return tree; 226 } 227 228 template <class T> 229 T BSTree<T>::minimum() 230 { 231 BSTNode<T> *p = minimum(mRoot); 232 if (p != NULL) 233 return p->key; 234 235 return (T)NULL; 236 } 237 238 /* 239 * 查找最大结点:返回tree为根结点的二叉树的最大结点。 240 */ 241 template <class T> 242 BSTNode<T>* BSTree<T>::maximum(BSTNode<T>* tree) 243 { 244 if (tree == NULL) 245 return NULL; 246 247 while(tree->right != NULL) 248 tree = tree->right; 249 return tree; 250 } 251 252 template <class T> 253 T BSTree<T>::maximum() 254 { 255 BSTNode<T> *p = maximum(mRoot); 256 if (p != NULL) 257 return p->key; 258 259 return (T)NULL; 260 } 261 262 /* 263 * 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。 264 */ 265 template <class T> 266 BSTNode<T>* BSTree<T>::successor(BSTNode<T> *x) 267 { 268 // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。 269 if (x->right != NULL) 270 return minimum(x->right); 271 272 // 如果x没有右孩子。则x有以下两种可能: 273 // (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。 274 // (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。 275 BSTNode<T>* y = x->parent; 276 while ((y!=NULL) && (x==y->right)) 277 { 278 x = y; 279 y = y->parent; 280 } 281 282 return y; 283 } 284 285 /* 286 * 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。 287 */ 288 template <class T> 289 BSTNode<T>* BSTree<T>::predecessor(BSTNode<T> *x) 290 { 291 // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。 292 if (x->left != NULL) 293 return maximum(x->left); 294 295 // 如果x没有左孩子。则x有以下两种可能: 296 // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。 297 // (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。 298 BSTNode<T>* y = x->parent; 299 while ((y!=NULL) && (x==y->left)) 300 { 301 x = y; 302 y = y->parent; 303 } 304 305 return y; 306 } 307 308 /* 309 * 将结点插入到二叉树中 310 * 311 * 参数说明: 312 * tree 二叉树的根结点 313 * z 插入的结点 314 */ 315 template <class T> 316 void BSTree<T>::insert(BSTNode<T>* &tree, BSTNode<T>* z) 317 { 318 BSTNode<T> *y = NULL; 319 BSTNode<T> *x = tree; 320 321 // 查找z的插入位置 322 while (x != NULL) 323 { 324 y = x; 325 if (z->key < x->key) 326 x = x->left; 327 else 328 x = x->right; 329 } 330 331 z->parent = y; 332 if (y==NULL) 333 tree = z; 334 else if (z->key < y->key) 335 y->left = z; 336 else 337 y->right = z; 338 } 339 340 /* 341 * 将结点(key为节点键值)插入到二叉树中 342 * 343 * 参数说明: 344 * tree 二叉树的根结点 345 * key 插入结点的键值 346 */ 347 template <class T> 348 void BSTree<T>::insert(T key) 349 { 350 BSTNode<T> *z=NULL; 351 352 // 如果新建结点失败,则返回。 353 if ((z=new BSTNode<T>(key,NULL,NULL,NULL)) == NULL) 354 return ; 355 356 insert(mRoot, z); 357 } 358 359 /* 360 * 删除结点(z),并返回被删除的结点 361 * 362 * 参数说明: 363 * tree 二叉树的根结点 364 * z 删除的结点 365 */ 366 template <class T> 367 BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z) 368 { 369 BSTNode<T> *x=NULL; 370 BSTNode<T> *y=NULL; 371 372 if ((z->left == NULL) || (z->right == NULL) ) 373 y = z; 374 else 375 y = successor(z); 376 377 if (y->left != NULL) 378 x = y->left; 379 else 380 x = y->right; 381 382 if (x != NULL) 383 x->parent = y->parent; 384 385 if (y->parent == NULL) 386 tree = x; 387 else if (y == y->parent->left) 388 y->parent->left = x; 389 else 390 y->parent->right = x; 391 392 if (y != z) 393 z->key = y->key; 394 395 return y; 396 } 397 398 /* 399 * 删除结点(z),并返回被删除的结点 400 * 401 * 参数说明: 402 * tree 二叉树的根结点 403 * z 删除的结点 404 */ 405 template <class T> 406 void BSTree<T>::remove(T key) 407 { 408 BSTNode<T> *z, *node; 409 410 if ((z = search(mRoot, key)) != NULL) 411 if ( (node = remove(mRoot, z)) != NULL) 412 delete node; 413 } 414 415 /* 416 * 销毁二叉树 417 */ 418 template <class T> 419 void BSTree<T>::destroy(BSTNode<T>* &tree) 420 { 421 if (tree==NULL) 422 return ; 423 424 if (tree->left != NULL) 425 return destroy(tree->left); 426 if (tree->right != NULL) 427 return destroy(tree->right); 428 429 delete tree; 430 tree=NULL; 431 } 432 433 template <class T> 434 void BSTree<T>::destroy() 435 { 436 destroy(mRoot); 437 } 438 439 /* 440 * 打印"二叉查找树" 441 * 442 * key -- 节点的键值 443 * direction -- 0,表示该节点是根节点; 444 * -1,表示该节点是它的父结点的左孩子; 445 * 1,表示该节点是它的父结点的右孩子。 446 */ 447 template <class T> 448 void BSTree<T>::print(BSTNode<T>* tree, T key, int direction) 449 { 450 if(tree != NULL) 451 { 452 if(direction==0) // tree是根节点 453 cout << setw(2) << tree->key << " is root" << endl; 454 else // tree是分支节点 455 cout << setw(2) << tree->key << " is " << setw(2) << key << "‘s " << setw(12) << (direction==1?"right child" : "left child") << endl; 456 457 print(tree->left, tree->key, -1); 458 print(tree->right,tree->key, 1); 459 } 460 } 461 462 template <class T> 463 void BSTree<T>::print() 464 { 465 if (mRoot != NULL) 466 print(mRoot, mRoot->key, 0); 467 } 468 469 #endif
mian.cpp
1 #include <iostream> 2 #include "BSTree.h" 3 using namespace std; 4 5 static int arr[]= {1,5,4,3,2,6}; 6 #define TBL_SIZE(a) ( (sizeof(a)) / (sizeof(a[0])) ) 7 8 int main() 9 { 10 int i, ilen; 11 BSTree<int>* tree=new BSTree<int>(); 12 13 cout << "== 依次添加: "; 14 ilen = TBL_SIZE(arr); 15 for(i=0; i<ilen; i++) 16 { 17 cout << arr[i] <<" "; 18 tree->insert(arr[i]); 19 } 20 21 cout << " == 前序遍历: "; 22 tree->preOrder(); 23 24 cout << " == 中序遍历: "; 25 tree->inOrder(); 26 27 cout << " == 后序遍历: "; 28 tree->postOrder(); 29 cout << endl; 30 31 cout << "== 最小值: " << tree->minimum() << endl; 32 cout << "== 最大值: " << tree->maximum() << endl; 33 cout << "== 树的详细信息: " << endl; 34 tree->print(); 35 36 cout << " == 删除根节点: " << arr[3]; 37 tree->remove(arr[3]); 38 39 cout << " == 中序遍历: "; 40 tree->inOrder(); 41 cout << endl; 42 43 // 销毁二叉树 44 tree->destroy(); 45 46 return 0; 47 }
以上是关于4树形结构二叉查找树的主要内容,如果未能解决你的问题,请参考以下文章