二叉树的实现_遍历_重构_树形显示

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 }

 

以上是关于二叉树的实现_遍历_重构_树形显示的主要内容,如果未能解决你的问题,请参考以下文章

python实现二叉树的遍历以及基本操作

剑指offer_重构二叉树

二叉树的实现

144_二叉树的前序遍历

数据结构之树(Tree)_二叉树的创建及遍历概述

Python实现二叉树的遍历