二叉树的实现_遍历_重构_树形显示
Posted 豆子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的实现_遍历_重构_树形显示相关的知识,希望对你有一定的参考价值。
1 //测试数据 2 //1 2 4 7 -1 -1 -1 5 -1 -1 3 -1 6 -1 -1 3 //1 2 4 11 -1 22 -1 -1 -1 5 -1 -1 3 6 -1 -1 7 -1 -1 4 5 6 #include <iostream> 7 #include <cstring> 8 using namespace std; 9 10 template<typename T> 11 struct BinaryNode 12 { 13 T element; 14 BinaryNode<T> *left; 15 BinaryNode<T> *right; 16 17 BinaryNode() : element(0), left(nullptr), right(nullptr) { } 18 BinaryNode(const T &theElement, BinaryNode *lt, BinaryNode *rt) 19 : element(theElement), left(lt), right(rt) {} 20 21 }; 22 23 24 template<typename T> 25 class BinarySearchTree 26 { 27 public: 28 BinarySearchTree() { 29 root = nullptr; 30 } 31 BinarySearchTree(const BinarySearchTree& rhs) { //复制构造函数 32 root = clone(rhs.root); 33 } 34 ~BinarySearchTree(); 35 36 void RootCreate(const T& end); //创建根结点的以下结点 37 38 bool contains(const T& x) const; 39 40 bool getNode(const T& e, const T&sub) { 41 if (getNode(e, root) != nullptr) { 42 getNode(e, root)->element = sub; //得到元素为e的结点 43 return true; 44 } 45 return false; 46 } 47 48 //求父亲的值 49 T getParents(const T& e) const { 50 return getParents(root, e); 51 } 52 53 bool isEmpty() const { 54 if (root == nullptr) 55 return true; 56 return false; 57 } 58 59 void PreprintTree() const { 60 PreprintTree(root); 61 } 62 63 void InprintTree() const { 64 InprintTree(root); 65 } 66 67 void PostprintTree() const { 68 PostprintTree(root); 69 } 70 71 void LevelprintTree() const { 72 LevelprintTree(root); 73 } 74 75 void PreprintTree_N() const { 76 PreprintTree_N(root); 77 } 78 79 void InprintTree_N() const { 80 InprintTree_N(root); 81 } 82 83 void PostprintTree_N() const { 84 PostprintTree_N(root); 85 } 86 87 void DisplayTreeShape(int level = 1) const { 88 DisplayTreeShape(root, level); 89 } 90 91 void makeEmpty(); 92 93 void remove(const T &x); 94 95 int Depth(); 96 int CountLeaf() { 97 BinaryNode<T> *p = root; 98 int count = 0; 99 CountLeaf(p, count); 100 return count; 101 } 102 103 const BinarySearchTree& operator = (const BinarySearchTree& rhs); 104 105 private: 106 107 BinaryNode<T> *root; //指向树根结点的指针 108 109 int Create(BinaryNode<T> *p, T end, int flag); 110 111 void remove(const T & x, BinaryNode<T> * & t, int rh); 112 113 bool contains(const T & x, BinaryNode<T> *t) const; 114 115 BinaryNode<T> * getNode(const T &x, BinaryNode<T> *t); 116 117 T getParents(BinaryNode<T> *p, const T& e) const; 118 119 void makeEmpty(BinaryNode<T> * & t); 120 //利用 递归 算法 计算树的 深度 121 int Depth(BinaryNode<T> * t, int level, int &depth); 122 //利用 递归 算法 计算树的 高度 123 void CountLeaf(BinaryNode<T> * t, int &count); 124 125 126 void PreprintTree(BinaryNode<T> * t) const; //先序遍历 127 void InprintTree(BinaryNode<T> *t) const; //中序遍历 128 void PostprintTree(BinaryNode<T> * t) const; //后序遍历 129 void LevelprintTree(BinaryNode<T> * t) const; //层次遍历 130 131 void PreprintTree_N(BinaryNode<T> * t) const; //非递归先序遍历 132 void InprintTree_N(BinaryNode<T> * t) const; //非递归中序遍历二叉树 133 void PostprintTree_N(BinaryNode<T> * t) const; //非递归后序遍历二叉树 134 void DisplayTreeShape(BinaryNode<T> *bt, int level) const; //二叉树的树形显示算法 135 136 137 BinaryNode<T> * clone(BinaryNode<T> * t) const; 138 }; 139 140 template<typename T> 141 bool BinarySearchTree<T>::contains(const T& x) const 142 { 143 return contains(x, root); 144 } 145 146 template<typename T> 147 bool BinarySearchTree<T>::contains(const T & x, BinaryNode<T> *t) const 148 { 149 bool judge; 150 if (t) { 151 if (t->element == x) 152 return true; 153 judge = contains(x, t->left); 154 if (judge) return true; 155 judge = contains(x, t->right); 156 if (judge) return true; 157 } 158 return false; 159 } 160 161 template<typename T> 162 BinaryNode<T>* BinarySearchTree<T>::getNode(const T & x, BinaryNode<T> *t) 163 { 164 BinaryNode<T>* ptemp; 165 if (t) 166 { 167 if (t->element == x) return t; 168 ptemp = getNode(x, t->left); 169 if (ptemp) return ptemp; 170 ptemp = getNode(x, t->right); 171 if (ptemp) return ptemp; 172 } 173 return nullptr; 174 } 175 176 template<typename T> 177 T BinarySearchTree<T>::getParents(BinaryNode<T> *p, const T& e) const 178 { 179 const int maxn = 1024; 180 BinaryNode<T> *Queue[maxn], *ptemp; 181 int front = 0, rear = 0; 182 if (p != nullptr && e != root->element) //为空,没有父节点, 且不为根结点 183 { 184 Queue[rear++] = p; //让根结点入队列,rear加1 185 while (front != rear) //栈不为空 186 { 187 ptemp = Queue[front++]; //将队列的结点依次出队 188 if ((ptemp->left && ptemp->right->element == e )|| (ptemp->right && ptemp->left->element == e)) 189 return ptemp->element; //如果是,则返回 190 else 191 { 192 if (ptemp->left) Queue[rear++] = ptemp->left; //左结点不为空,则入栈 193 if (ptemp->right) Queue[rear++] = ptemp->right; //右不为空,则入栈 194 } 195 } 196 } 197 return -1; 198 } 199 200 201 template<typename T> 202 void BinarySearchTree<T>::RootCreate(const T& end) //创建二叉树 203 { 204 cout << "请按先序序列的顺序输入二叉树,-1为空指针域标志:" << endl; 205 BinaryNode<T> *p; 206 int x; 207 cin >> x; 208 if (x == end) return; 209 p = new BinaryNode<T>(x, nullptr, nullptr); 210 root = p; 211 Create(p, end, 1); 212 Create(p, end, 2); 213 } 214 215 template<typename T> 216 int BinarySearchTree<T>::Create(BinaryNode<T> *p, T end, int flag) 217 { 218 BinaryNode<T> *t; 219 T x; 220 cin >> x; 221 if (x != end) 222 {//子节点的左右结点先赋值 223 t = new BinaryNode<T>(x, nullptr, nullptr); 224 if (flag == 1) p->left = t; //标志i=1,代表左孩子 225 if (flag == 2) p->right = t; //i=2结点为右孩子 226 Create(t, end, 1); //递归调用,直到 x == end 227 Create(t, end, 2); 228 } 229 return 0; 230 } 231 232 template<typename T> 233 void BinarySearchTree<T>::remove(const T &x) 234 { 235 remove(x, root, 1); 236 remove(x, root, 2); 237 } 238 239 /************************************************************************/ 240 /* x is item to remove */ 241 /* t is the node that roots the subtree */ 242 /* Set the new root of the subtree */ 243 /* 1.结点是一片树叶时 -- 可被立即删除*/ 244 /* 2.结点有一个儿子, 则该结点可以在其父节点调整他的链 以绕过该结点后被删除 */ 245 /* 3.结点有两个儿子, 则其右子树的最小数据代替该结点的数据,并递归删除那个结点 */ 246 /* 注: 右子树中的最小的结点不可能有左结点 */ 247 /************************************************************************/ 248 template<typename T> 249 void BinarySearchTree<T>::remove(const T &x, BinaryNode<T> * & t, int rh) 250 { 251 if (t == nullptr) return; 252 if (t->element == x && rh == 1) 253 { 254 makeEmpty(t->left); 255 } 256 else { 257 makeEmpty(t->right); 258 } 259 remove(x, t->left, rh); 260 remove(x, t->right, rh); 261 } 262 263 /************************************************************************/ 264 ///* Destructor for the tree 265 /************************************************************************/ 266 template<typename T> 267 BinarySearchTree<T>::~BinarySearchTree() 268 { 269 makeEmpty(); 270 } 271 272 template<typename T> 273 void BinarySearchTree<T>::makeEmpty() //公有函数 274 { 275 makeEmpty(root); 276 } 277 278 /************************************************************************/ 279 ///* Internal method to make subtree empty -- 私有函数 280 /************************************************************************/ 281 template<typename T> 282 void BinarySearchTree<T>::makeEmpty(BinaryNode<T> * & t) 283 { 284 if (t != nullptr) 285 { 286 makeEmpty(t->left); 287 makeEmpty(t->right); 288 delete t; 289 } 290 t = nullptr; 291 } 292 293 /************************************************************************/ 294 ///* Deep copy 295 /************************************************************************/ 296 template<typename T> 297 const BinarySearchTree<T>& BinarySearchTree<T>::operator = (const BinarySearchTree &rhs) 298 { 299 if (this != &rhs) { 300 makeEmpty(); 301 root = clone(rhs.root); 302 } 303 return *this; 304 } 305 306 /************************************************************************/ 307 ///* Internal method to clone subtree. -- 递归复制结点 308 /************************************************************************/ 309 template<typename T> 310 BinaryNode<T>* BinarySearchTree<T>::clone(BinaryNode<T> * t) const 311 { 312 if (t == nullptr) 313 return nullptr; 314 return new BinaryNode<T>(t->element, clone(t->left), clone(t->right)); 315 } 316 317 //利用递归计算树的深度 318 template<typename T> 319 int BinarySearchTree<T>::Depth() 320 { 321 BinaryNode<T> *t = root; 322 int depth = 0; 323 if (root == nullptr) 324 return 0; 325 Depth(t, 1, depth); 326 return depth; 327 } 328 329 //由public的函数Depth调用, 完成树的深度的计算,p是根结点,Level是层,depth用来返回树的深度 330 template<typename T> 331 int BinarySearchTree<T>::Depth(BinaryNode<T> *t, int level, int &depth) 332 { 333 if (level > depth) depth = level; //层数 334 if (t->left) Depth(t->left, level + 1, depth); //递归遍历左子树,且层数加1 335 if (t->right) Depth(t->right, level + 1, depth); //递归遍历右子树, 且层数加1 336 return 0; 337 } 338 339 template<typename T> 340 //利用 递归 算法 计算树的 高度 341 void BinarySearchTree<T>::CountLeaf(BinaryNode<T> * t, int &count) 342 { 343 if (t == nullptr) return; //为空时,退出 344 345 // CountLeaf(t->left, count); 346 // CountLeaf(t->right, count); 347 if (!(t->left) && !(t->right)) { //儿子为空时 348 count++; 349 } 350 CountLeaf(t->left, count); 351 CountLeaf(t->right, count); 352 } 353 354 355 /************************************************************************/ 356 ///* printTree --- 前序遍历 357 /************************************************************************/ 358 template<typename T> 359 void BinarySearchTree<T>::PreprintTree(BinaryNode<T> * t) const 360 { 361 if (t != nullptr) { 362 cout << t->element << ‘ ‘; 363 PreprintTree(t->left); 364 PreprintTree(t->right); 365 } 366 } 367 368 //中序遍历 369 template<typename T> 370 void BinarySearchTree<T>::InprintTree(BinaryNode<T> * t) const 371 { 372 if (t != nullptr) { 373 InprintTree(t->left); 374 cout << t->element << ‘ ‘; 375 InprintTree(t->right); 376 } 377 } 378 379 //后序遍历 380 template<typename T> 381 void BinarySearchTree<T>::PostprintTree(BinaryNode<T> * t) const 382 { 383 if (t != nullptr) { 384 PostprintTree(t->left); 385 PostprintTree(t->right); 386 cout << t->element << ‘ ‘; 387 } 388 } 389 390 //利用队列Queue层次遍历二叉树 391 template<typename T> 392 void BinarySearchTree<T>::LevelprintTree(BinaryNode<T> * t) const 393 { 394 const int maxn = 1024; 395 BinaryNode<T> *Queue[maxn]; //一维数组作为队列 396 BinaryNode<T> *tmp; 397 int front = 0, rear = 0; //队列初始为空 398 if (root) { 399 Queue[rear++] = root; //二叉树的根结点指针入队列 400 while (front != rear) 401 { 402 tmp = Queue[front++]; //队首的元素出队列 403 if (tmp) cout << tmp->element << ‘ ‘; //输出结点值 404 if (tmp->left) Queue[rear++] = tmp->left; 405 if (tmp->right) Queue[rear++] = tmp->right; 406 } 407 } 408 } 409 410 //先序遍历 (DLR) 411 template<typename T> 412 void BinarySearchTree<T>::PreprintTree_N(BinaryNode<T> * t) const //非递归先序遍历 413 { 414 const int maxn = 1024; 415 BinaryNode<T> *Stack[maxn]; 416 int top = 0; 417 BinaryNode<T> *tmp = root; //将根结点的指针赋值给tmp 418 419 // cout << "Debug :\n"; 420 while (tmp || top != 0) 421 { 422 // cout << "debug : \n"; 423 while (tmp) { 424 cout << tmp->element << ‘ ‘; 425 Stack[top++] = tmp; //右孩子入栈 426 tmp = tmp->left; //一直递归到最左的结点 427 } 428 if (top) { //栈不为空, 从栈中取出一个结点指针 429 tmp = Stack[--top]; 430 tmp = tmp->right; 431 } 432 } 433 } 434 435 //中序非递归遍历二叉树 (LDR) 436 template<typename T> 437 void BinarySearchTree<T>::InprintTree_N(BinaryNode<T> * t) const //非递归中序遍历二叉树 438 { 439 const int maxn = 1024; 440 BinaryNode<T> *Stack[maxn]; 441 int top = 0; 442 BinaryNode<T> *tmp = root; 443 444 while (tmp || top != 0) 445 { 446 while (tmp) { //迭代到最左的子树 447 Stack[top++] = tmp; //左子树入栈 448 tmp = tmp->left; 449 } 450 if (top) { 451 tmp = Stack[--top]; //出栈最左的子树 452 cout << tmp->element << ‘ ‘; //输出该元素 453 tmp = tmp->right; //并指向右结点开始迭代 454 } 455 } 456 457 } 458 459 //非递归后序遍历二叉树 (LRD) 460 template<typename T> 461 void BinarySearchTree<T>::PostprintTree_N(BinaryNode<T> * t) const 462 { 463 const int maxn = 1024; 464 struct Mystack { 465 BinaryNode<T> * link; 466 int flag; 467 }; 468 469 Mystack Stack[maxn]; 470 BinaryNode<T> * p = root, *tmp; 471 472 if (root == nullptr) return; 473 474 int top = -1, //栈顶初始化 475 sign = 0; //为结点tmp 的标志量 476 477 while (p != nullptr || top != -1) 478 { 479 while (p != nullptr) //遍历到最左 480 { 481 Stack[++top].link = p; //并且一直入栈 482 Stack[top].flag = 1; //设置flag为第一次入栈 483 p = p->left; 484 } 485 486 if (top != -1) 487 { 488 tmp = Stack[top].link; 489 sign = Stack[top].flag; 490 top--; //出栈 491 492 if (sign == 1) //结点第一次进栈 493 { 494 top++; 495 Stack[top].link = tmp; 496 Stack[top].flag = 2; //标记为第二次出栈 497 p = tmp->right; 498 } 499 else { //第二次出栈就输出 500 cout << tmp->element << ‘ ‘; //访问该结点数据域 501 p = nullptr; 502 } 503 } 504 505 } 506 507 } 508 509 //树形显示二叉树,也是中序遍历 510 template<typename T> 511 void BinarySearchTree<T>::DisplayTreeShape(BinaryNode<T> *bt, int level) const 512 { 513 if (bt) //二叉树的树形显示算法 514 { 515 DisplayTreeShape(bt->right, level + 1); //空二叉树不显示 516 cout << endl; 517 for (int i = 0; i < level - 1; i++) 518 cout << " "; //确保在第level列显示结点 519 cout << bt->element; 520 DisplayTreeShape(bt->left, level + 1); //显示左子树 521 } 522 } 523 524 //先序(preorder) -- 中序(inorder) ===> 得到后序遍历(postorder) 525 //先序为了得到根结点, 中序为了得到左右两个子序列 526 template<typename T> 527 void BinaryTreeFromOrderings(const T *inorder, const T *preorder, int length) 528 { 529 if (length == 0) return; 530 T node_value = *preorder; //得到先序序列的第一个元素 ==> 根结点 531 int rootIndex = 0; //根结点的索引 532 for (; rootIndex < length; rootIndex++) { //在中序序列中,遍历到(先序遍历的)根结点的地方终止 533 if (inorder[rootIndex] == *preorder) 534 break; 535 } 536 537 /******************* Left Root Right *********************/ 538 //left -- 中序遍历开始的位置,后序遍历开始的位置 可以遍历的总长度 539 BinaryTreeFromOrderings(inorder, preorder + 1, rootIndex); 540 //Right 541 BinaryTreeFromOrderings(inorder + rootIndex + 1, preorder + rootIndex + 1, length - (rootIndex + 1)); 542 cout << node_value << ‘ ‘; 543 } 544 545 546 int main() 547 { 548 int testData; 549 BinarySearchTree<int> test; 550 cout << "创建树: \n"; 551 test.RootCreate(-1); 552 553 cout << "\n全部元素为: \n"; 554 test.PreprintTree(); 555 556 cout << endl; 557 558 cout << "输入查找元素: \n"; 559 cin >> testData; 560 cout << "是否包含 " << testData << " : " << test.contains(testData) << endl; 561 562 cout << testData << "的父亲是:\t"; 563 cout << test.getParents(testData) << endl; 564 565 cout << endl; 566 cout << "输入修改元素: \n"; 567 cin >> testData; 568 if (test.getNode(testData, 1000)) 569 cout << "OK !\n"; 570 test.PreprintTree(); 571 cout << "\n"; 572 573 cout << "\n树的高度: " << test.Depth() << endl; 574 cout << "\n叶子的个数: " << test.CountLeaf() << endl; 575 cout << endl; 576 577 cout << "先序遍历树元素: \n"; 578 test.PreprintTree(); 579 580 cout << "\n\n中序遍历树元素: \n"; 581 test.InprintTree(); 582 583 cout << "\n\n后序遍历树元素: \n"; 584 test.PostprintTree(); 585 586 cout << "\n\n层次遍历树元素: \n"; 587 test.LevelprintTree(); 588 589 cout << "\n\n先序遍历树元素(非递归): \n"; 590 test.PreprintTree_N(); 591 592 cout << "\n\n中序遍历树元素(非递归): \n"; 593 test.InprintTree_N(); 594 595 cout << "\n\n后序遍历树元素(非递归): \n"; 596 test.PostprintTree_N(); 597 598 cout << "\n\n二叉树的树形显示算法(下面是逆时针旋转了90°的树): \n"; 599 test.DisplayTreeShape(43); 600 601 cout << endl; 602 603 const char* pr = "ABCDEFGHI"; //GDAFEMHZ 604 const char* in = "BCAEDGHFI"; //ADEFGHMZ 605 BinaryTreeFromOrderings(in, pr, strlen(pr)); 606 607 cout << endl; 608 609 return 0; 610 }
以上是关于二叉树的实现_遍历_重构_树形显示的主要内容,如果未能解决你的问题,请参考以下文章