【1】树的基本概念

1: 树属于一种非线性数据结构

2: 树以分支关系描述数据元素之间的层次结构

3: 树(tree)是 n(n≥0) 个结点的有限集

4: 树的结构中,有且仅有一个特殊的结点,称为树的根结点(root)

5: 树中存在唯一的称为根的数据元素

6: 树中各子树是互不相交的集合

7: 树的根结点没有前驱结点,除根之外的所有结点都有且只有一个前驱结点

8: 树中所有的结点可以有0个或多个后继结点

9: 结点(node)——表示树中的数据元素

10: 结点的度(degree)——结点的子树个数

11: 树的度——树中结点的最大度值

12: 叶子(leaf)结点——度为0的结点

13: 分支结点——除叶子结点外的所有结点(度不为0)

14: 孩子(child)——结点的子树的根称为此结点的孩子

15: 双亲(parents)——此结点称为孩子的双亲

16: 兄弟(sibling)——具有同一双亲的孩子结点互称兄弟

17: 结点的层次(level)——从根结点算起,根为第一层,它的孩子为第二层等以此类推

18: 树的深度(depth)——树中结点的最大层次数

19: 有序树——树中各结点的子树看成从左到右是有次序的(即就是子树位置不可以互换)

20: 森林(forest)——m(m >= 0)棵互不相交的树的集合。

 将一棵非空树的根结点删去,树就变成一个森林;反之,给一个森林增加一个统一的根结点,森林就变成一棵树。

21: 二叉树是n(n>0)个结点的有限集,它或为空树(n=0),或由一个根结点和两棵分别称为左子树和右子树的互不相交的二叉树构成

22: 树的高度:从结点x(某棵树的根结点)向下到某个叶结点最长简单路径中边的条数

备注:

对于整棵树而言,树的高度和深度是相等的。

而对于树中相同深度的每个结点来说,它们的高度却不一定相同。

【2】树的表示

【3】二叉树

(1)二叉树的定义

我们把满足以下两个条件的树形结构叫做二叉树(Binary Tree): �    

1. 每个结点的度都不大于2; �    

2. 每个结点的孩子结点次序不能任意颠倒。  

由此定义可以看出:一个二叉树中的每个结点只能拥有0、1或2个孩子,而且每个孩子有左右之分。

而且我们把位于左边的孩子叫做左孩子,位于右边的孩子叫做右孩子。

(2)二叉树的五种基本形态

(3)二叉树的性质

(4)满二叉树和完全二叉树

在满二叉树中,每层结点都是满的,即每层结点都具有最大结点数的二叉树。

深度为k,结点数为n的二叉树,如果其结点1~n的位置序号分别与满二叉树的结点1~n的位置序号一一对应,则为完全二叉树。

满二叉树必为完全二叉树, 而完全二叉树不一定是满二叉树。

 

(5)完全二叉树的两个重要性质

(6)二叉树的存储结构

二叉树的结构是非线性的,每一结点最多可有两个后继。 �

二叉树的存储结构有两种: 顺序存储结构和链式存储结构。

1. 顺序存储结构

2. 链式存储结构

  二叉树的链式存储结构代码实现如下:

  1 // BinTree实现代码
  2 #include <iostream>
  3 #include <fstream>
  4 #include "Queue.h"
  5 #include "Stack.h"
  6 using namespace std;
  7 
  8 template<class Type>
  9 Type Max(const Type & a, const Type & b)
 10 {
 11     return a > b ? a : b;
 12 }
 13 
 14 template<class Type>
 15 class BinaryTree;
 16 
 17 template<class Type>
 18 class BinTreeNode
 19 {
 20     friend class BinaryTree<Type>;
 21 private:
 22     BinTreeNode<Type> *leftChild, *rightChild;
 23     Type data;
 24 
 25 public:
 26     BinTreeNode():leftChild(NULL), rightChild(NULL)
 27     {}
 28     BinTreeNode(const Type &x, BinTreeNode<Type> *left = NULL, BinTreeNode<Type> *right = NULL)
 29         : data(x)
 30         , leftChild(left)
 31         , rightChild(right)
 32     {}
 33     ~BinTreeNode()
 34     {}
 35 
 36 public:
 37     Type & GetData() 
 38     { 
 39         return data;
 40     }
 41     BinTreeNode<Type> *& GetLeft() 
 42     { 
 43         return leftChild;
 44     }
 45     void SetLeft(BinTreeNode<Type>* & pLeft) 
 46     { 
 47         leftChild = pLeft;
 48     }
 49     BinTreeNode<Type> *& GetRight() 
 50     { 
 51         return rightChild;
 52     }
 53     void SetRight(BinTreeNode<Type>* & pRight)
 54     {
 55         rightChild = pRight;
 56     }
 57     Type const & GetData() const 
 58     {
 59         return data;
 60     }
 61     BinTreeNode<Type> * const & GetLeft() const 
 62     {
 63         return leftChild;
 64     }
 65     BinTreeNode<Type> * const & GetRight() const 
 66     { 
 67         return rightChild;
 68     }
 69 };
 70 
 71 template<class Type>
 72 class BinaryTree
 73 {
 74 private:
 75     BinTreeNode<Type> *root;
 76     Type RefValue;     
 77     //创建二叉树的两种方式:
 78     void CreateTree(BinTreeNode<Type> *&t)
 79     {
 80         Type item;
 81         cin >> item;
 82         if (item == RefValue)
 83         {
 84             t = NULL;
 85         }
 86         else
 87         {
 88             t = new BinTreeNode<Type>(item);
 89             CreateTree(t->leftChild);
 90             CreateTree(t->rightChild);
 91         }
 92     }
 93     void CreateTree(BinTreeNode<Type> *&t, istream &in)
 94     {
 95         Type item;
 96         in >> item;
 97         if (item == RefValue)
 98         {
 99             t = NULL;
100         }
101         else
102         {
103             t = new BinTreeNode<Type>(item);
104             CreateTree(t->leftChild, in);
105             CreateTree(t->rightChild, in);
106         }
107     }
108     // 先序遍历
109     void PreOrder(const BinTreeNode<Type> *t)const
110     {
111         if (t != NULL)
112         {
113             cout << t->data << " ";
114             PreOrder(t->leftChild);
115             PreOrder(t->rightChild);
116         }
117     }
118     // 中序遍历
119     void InOrder(const BinTreeNode<Type> *t) const
120     {
121         if (t != NULL)
122         {
123             InOrder(t->leftChild);
124             cout << t->data << " ";
125             InOrder(t->rightChild);
126         }
127     }
128     // 后序遍历
129     void PostOrder(const BinTreeNode<Type> *t) const
130     {
131         if (t != NULL)
132         {
133             PostOrder(t->leftChild);
134             PostOrder(t->rightChild);
135             cout << t->data << " ";
136         }
137     }
138     // 大小
139     int Size(BinTreeNode<Type> *t) const
140     {
141         return (NULL == t) ? 0 : 1 + Size(t->leftChild) + Size(t->rightChild); 
142     }
143     // 深度
144     int Depth(BinTreeNode<Type> *t) const
145     {
146         return (NULL == t) ? 0 : 1 + Max(Depth(t->leftChild), Depth(t->rightChild));
147     }
148     // 摧毁二叉树
149     void DestroyTree(BinTreeNode<Type> *t)
150     {
151         if (t != NULL)
152         {
153             DestroyTree(t->leftChild);
154             DestroyTree(t->rightChild);
155             delete t;
156         }
157     }
158     // 拷贝
159     BinTreeNode<Type>* Copy(const BinTreeNode<Type> *r) const
160     {
161         if (NULL == r)
162         {
163             return NULL;
164         }
165         else
166         {
167             BinTreeNode<Type> *s = new BinTreeNode<Type>(r->data);
168             s->leftChild = Copy(r->leftChild);
169             s->rightChild = Copy(r->rightChild);
170             return s;
171         }
172     }
173     // 查找某元素
174     BinTreeNode<Type> * Find(BinTreeNode<Type> *cur, const Type &x) const
175     {
176         if (NULL == cur) 
177         { 
178             return NULL;
179         }
180         else
181         {
182             if (x == cur->data) 
183                 return cur;
184             BinTreeNode<Type> *p = NULL;
185             if ((p = Find(cur->leftChild, x)) != NULL)
186                 return p;
187             else
188                 return Find(cur->rightChild, x);
189         }
190     }
191     // 父亲节点
192     BinTreeNode<Type> *Parent(BinTreeNode<Type> *start,
193                               const BinTreeNode<Type> *current) const
194     {
195         if (NULL == start) 
196         {
197             return NULL;
198         }
199         else
200         {
201             if (start->leftChild == current || start->rightChild == current)
202             {
203                 return start;
204             }
205             BinTreeNode<Type> *p = NULL;
206             if ((p = Parent(start->leftChild, current)) != NULL)
207                 return p;
208             else
209                 return Parent(start->rightChild, current);
210         }
211     }
212     // 判相等
213     bool Equal(const BinTreeNode<Type> *a, const BinTreeNode<Type> *b) const
214     {
215         if (NULL == a && NULL == b)
216         {
217             return true;
218         }
219         else if (NULL == a || NULL == b)
220         {
221             return false;
222         }
223         else 
224         {
225             if (a->data != b->data)
226                 return false;
227             else
228                 return (Equal(a->leftChild, b->leftChild) &&
229                         Equal(a->rightChild, b->rightChild));
230         }
231     }
232     // 利用栈实现先序遍历
233     void PreOrderByStack(BinTreeNode<Type>* p) const
234     {
235         SeqStack<const BinTreeNode<Type> *> sT;
236         const BinTreeNode<Type> *s = NULL;
237         if (p != NULL)
238             sT.Push(p);
239         while (!sT.IsEmpty())
240         {
241             sT.Pop(s);
242             cout << s->data << " ";
243             if (s->rightChild != NULL)
244                 sT.Push(s->rightChild);
245             if (s->leftChild)
246                 sT.Push(s->leftChild);
247         }
248     }
249     // 利用栈实现中序遍历
250     void InOrderByStack(BinTreeNode<Type>* p) const
251     {
252         SeqStack<const BinTreeNode<Type> *> sT;
253         const BinTreeNode<Type> *s = NULL;
254         if (p != NULL)
255             sT.Push(p);
256         while (!sT.IsEmpty())
257         {
258             while (sT.GetTop(s) && s != NULL)
259             {
260                 sT.Push(s->leftChild);
261             }
262             sT.Pop(s); //空值退栈
263             if (!sT.IsEmpty())
264             {
265                 sT.Pop(s);
266                 cout << s->data << " ";
267                 sT.Push(s->rightChild);
268             }
269         }
270     }
271     // 利用栈实现后序遍历(有标记位)
272     void PostOrderByStackFlag(const BinTreeNode<Type>* p) const
273     {
274         SeqStack<const BinTreeNode<Type> *> sT;
275         const BinTreeNode<Type> *s = NULL;
276         do
277         {
278             while (p != NULL)  
279             { 
280                 sT.Push(p); 
281                 p = p->leftChild;
282             }
283             s = NULL;
284             while (!sT.IsEmpty())
285             {  
286                 sT.GetTop(p);
287                 if (p->rightChild == s)  //t:表示为null 或者 右子节点被访问过了。  
288                 {  
289                     cout << p->data << " ";
290                     sT.Pop(p);
291                     s = p;  //记录下刚刚访问的节点  
292                 }
293                 else 
294                 {  
295                     p = p->rightChild;  
296                     break;
297                 }
298             }
299         } while (!sT.IsEmpty());
300     }
301     // 利用栈实现后序遍历(无标记位)
302     void PostOrderByStack(const BinTreeNode<Type>* p) const
303     {
304         SeqStack<const BinTreeNode<Type> *> sT;
305         if (NULL == p)
306             return;
307         while (1)
308         {
309             while (p)
310             {
311                 sT.Push(p);
312                 p = p->leftChild;
313             }
314             sT.GetTop(p);
315             while (NULL == p)
316             {
317                 sT.Pop(p);
318                 sT.Pop(p);
319                 cout << p->data << " ";
320                 if (sT.IsEmpty())
321                     return;
322                 sT.GetTop(p);
323             }
324             sT.Push(NULL);
325             p = p->rightChild;
326         }
327     }
328     // 利用队列实现层次遍历
329     void LevelOrder(BinTreeNode<Type> * p)
330     {
331         SeqQueue<const BinTreeNode<Type> *>   sQ;
332         const BinTreeNode<Type> *s = NULL;
333         if (p != NULL)
334             sQ.EnQueue(p);
335         while (!sQ.IsEmpty())
336         {
337             sQ.DeQueue(s);
338             cout << s->data << " ";
339             if (s->leftChild != NULL)
340             {
341                 sQ.EnQueue(s->leftChild);
342             }
343             if (s->rightChild != NULL)
344             {
345                 sQ.EnQueue(s->rightChild);
346             }
347         }
348         cout << endl;
349     }
350 public:
351     BinaryTree():root(NULL)
352     {}
353     BinaryTree(Type x):RefValue(x), root(NULL)
354     {}
355     BinaryTree(BinaryTree<Type> &bt):RefValue(bt.RefValue)
356     {
357         root = bt.Copy();
358     }
359 
360     BinaryTree<Type> & operator=(const BinaryTree<Type> &bt)
361     {
362         if (this != &bt)
363         {
364             DestroyTree(root);
365             root = bt.Copy(bt.root);
366         }
367         return *this;
368     }
369 
370     ~BinaryTree()
371     {
372         DestroyTree(root);
373         root = NULL;
374     }
375 public:
376     BinTreeNode<Type> * GetRoot() 
377     { 
378         return root;
379     }
380 
381     BinTreeNode<Type> * Copy()
382     {
383         return Copy(root);
384     }
385 
386     void CreateTree()
387     {
388         CreateTree(root);
389     }
390 
391     void CreateTree(istream &in)
392     {
393         CreateTree(root, in);
394     }
395 
396     void PreOrder() const
397     {
398         PreOrder(root);
399         cout << endl;
400     }
401 
402     void InOrder() const
403     {
404         InOrder(root);
405         cout << endl;
406     }
407 
408     void PostOrder() const
409     {
410         PostOrder(root);
411         cout << endl;
412     }
413 
414     void PreStack() const
415     {
416         PreOrderByStack(root);
417         cout << endl;
418     }
419 
420     void InStack() const
421     {
422         InOrderByStack(root);
423         cout << endl;
424     }
425 
426     void PostStack() const
427     {
428         PostOrderByStack(root);
429         cout << endl;
430     }
431 
432     void PostStackFlag() const
433     {
434         PostOrderByStackFlag(root);
435         cout << endl;
436     }
437 
438     void LevelOrder()
439     {
440         LevelOrder(root);
441     }
442     // 所有遍历方式:
443     void Traverse()
444     {
445         cout << "先序遍历:";
446         PreOrder();
447         cout << "中序遍历:";
448         InOrder();
449         cout << "后序遍历:";
450         PostOrder();
451         cout << "利用队列层次遍历:";
452         LevelOrder();
453         cout << "利用栈先序遍历:";
454         PreStack();
455         cout << "利用栈中序遍历:";  
456         InStack();
457         cout << "利用栈后序遍历(有标记位):";
458         PostStackFlag();
459         cout << "利用栈后序遍历(无标记位):";
460         PostStack();
461     }
462 
463     int Size() const
464     {
465         return Size(root);
466     }
467 
468     int Depth() const
469     {
470         return Depth(root);
471     }
472 
473     void DestroyTree()
474     {
475         DestroyTree(root);
476         root = NULL;
477     }
478     // 插入元素
479     bool Insert(const Type& item)
480     {
481         BinTreeNode<Type> *newnode = new BinTreeNode<Type>(item);
482         if (NULL == root)
483         {
484             root = newnode;
485             return true;
486         }
487 
488         BinTreeNode<Type> *pItem = Find(item);
489         if (pItem != NULL)
490         {
491             cout << "The item " << item << " is exist!" <<endl;
492             return false;
493         }
494         
495         BinTreeNode<Type> *pstart = root;
496         while (1)
497         {
498             if (item < pstart->data)
499             {
500                 if (NULL == pstart->leftChild)
501                 {
502                     pstart->leftChild = newnode;
503                     return true;
504                 }
505                 pstart = pstart->leftChild;    
506             }
507             else
508             {
509                 if (NULL == pstart->rightChild)
510                 {
511                     pstart->leftChild = newnode;
512                     return true;
513                 }
514                 pstart = pstart->rightChild;
515             }
516         }
517     }
518 
519     BinTreeNode<Type> * Parent(const BinTreeNode<Type> *current)const
520     {
521         return (NULL == root || root == current) ? NULL : Parent(root, current);
522     }
523 
524     BinTreeNode<Type> *LeftChild(BinTreeNode<Type> *current)const
525     {
526         return current->leftChild;
527     }
528 
529     BinTreeNode<Type> *RightChild(BinTreeNode<Type> *current) const
530     {
531         return current->rightChild;
532     }
533 
534     BinTreeNode<Type> *Find(const Type &x) const
535     {
536         return NULL == root ? NULL : Find(root, x);
537     }
538 
539     bool Equal(const BinaryTree<Type> & bt) const
540     {
541         return Equal(root, bt.root);
542     }
543 
544     friend bool operator==(const BinaryTree<Type> &bt1, const BinaryTree<Type> &bt2);
545 
546     template<class Type>
547     friend istream & operator>>(istream &in, BinaryTree<Type> &bt);
548     template<class Type>
549     friend ostream & operator<<(ostream &out, const BinaryTree<Type> &bt);
550 };
551 
552 template<class Type>
553 istream & operator>>(istream &in, BinaryTree<Type> &bt)
554 {
555     bt.CreateTree(in);
556     return in;
557 }
558 
559 template<class Type>
560 ostream & operator<<(ostream &out, const BinaryTree<Type> &bt)
561 {
562     bt.InOrder();    //按中序输出
563     return out;
564 }
565 
566 template<class Type>
567 bool operator ==(const BinaryTree<Type> &bt1, const BinaryTree<Type> &bt2)
568 {
569     return bt1.Equal(bt2);
570 }
571 //////////////////////////////////////////////////
572 void main()
573 {
574     BinaryTree<char> mytree('#');
575     ifstream ifile("Test.txt", ios::in);
576     if (!ifile)
577         return;
578     // 创建二叉树
579     ifile >> mytree;
580     // 输出二叉树
581     cout << "重载输出操作符,输出二叉树:"<< mytree;
582 
583     BinTreeNode<char> *s = mytree.Find('E');
584     cout << "查找节点E: " << s->GetData() << endl;
585     BinTreeNode<char> *p = mytree.Parent(s);
586     cout << "查找节点E的父节点:" << p->GetData() << endl;
587     
588     cout << "所有遍历二叉树方式及其结果如下:" << endl;
589     mytree.Traverse();
590     
591     cout << "二叉树的节点数:" << mytree.Size() << endl;
592     cout << "二叉树的深度:" << mytree.Depth() << endl;
593 
594     cout << "拷贝构造函数重新构建新的二叉树youtree" << endl;
595     BinaryTree<char>   youtree(mytree);
596     cout << "youtree 与 mytree  相等 ? " << youtree.Equal(mytree) << endl;
597     // 测试插入函数
598     if (mytree.Insert('I'))
599     {
600         cout << "插入成功后再遍历二叉树:" << endl;
601         mytree.Traverse();
602     }
603 }
View Code

以上代码中引用的queue.h文件和stack.h文件可以从《队列》 和 《》两篇随笔中拷贝即可。

(7)二叉树的遍历和创建二叉树

1. 二叉树的遍历

假使用L、D、R分别表示遍历左子树、访问根结点、遍历右子树

那么对二叉树的遍历顺序就可以有六种方式: �

a. 访问根,遍历左子树,遍历右子树(记做DLR)

b. 访问根,遍历右子树,遍历左子树(记做DRL)

c. 遍历左子树,访问根,遍历右子树(记做LDR)

d. 遍历左子树,遍历右子树,访问根(记做LRD)

e. 遍历右子树,访问根,遍历左子树(记做RDL)

f. 遍历右子树,遍历左子树,访问根(记做RLD)

二叉树的遍历常用为三种:先序,中序,后序

先序遍历(DLR)即就是先根遍历

中序遍历(LDR)即就是中根遍历

后序遍历(LRD)即就是后根遍历

三种遍历示例如下:

2. 创建二叉树

a. 由先序序列创建二叉树

b. 先序和中序创建二叉树

c. 中序和后序创建二叉树

三种创建二叉树方式实现代码如下:

  1 #include <stdio.h>
  2 #include <malloc.h>
  3 
  4 typedef char TElemType;
  5 
  6 typedef struct BiTNode
  7 {
  8     struct BiTNode *leftChild, *rightChild;
  9     TElemType data;
 10 } BiTNode, *BiTree;
 11 
 12 //初始化
 13 void InitTree(BiTree &t)
 14 {
 15     t = NULL;
 16 }
 17 // 先序遍历
 18 void PreOrder(BiTree &t)
 19 {
 20     if (t != NULL)
 21     {
 22         printf("%c ", t->data);
 23         PreOrder(t->leftChild);
 24         PreOrder(t->rightChild);
 25     }
 26 }
 27 // 中序遍历
 28 void InOrder(BiTree &t)
 29 {
 30     if (t != NULL)
 31     {
 32         InOrder(t->leftChild);
 33         printf("%c ", t->data);
 34         InOrder(t->rightChild);
 35     }
 36 }
 37 // 后序遍历
 38 void PostOrder(BiTree t)
 39 {
 40     if (t != NULL)
 41     {
 42         PostOrder(t->leftChild);
 43         PostOrder(t->rightChild);
 44         printf("%c ", t->data);
 45     }
 46 }
 47 // 由先序和中序创建二叉树
 48 void  Pre_In_Create(char *pre, char *in, int len, BiTree &t)
 49 {
 50     if (len <= 0) return;
 51     char *p = NULL, *q = NULL;
 52     int i = 0;
 53     t = (BiTree)malloc(sizeof(BiTNode));
 54     t->data = pre[0];    // 根节点
 55     t->leftChild = NULL;
 56     t->rightChild = NULL;
 57     while (i < len)
 58     {
 59         if (*(in + i) == pre[0])
 60             break;
 61         ++i;
 62     }
 63     p = pre + 1;      // 左子树的先序序列
 64     q = in;
 65     Pre_In_Create(p, q, i, t->leftChild);
 66     p = pre + i + 1;  // 右子树的先序序列
 67     q = in + i + 1;
 68     Pre_In_Create(p, q, len-i-1, t->rightChild);
 69 }
 70 // 由中序后序创建二叉树
 71 void  In_Pos_Create(char *in, char *pos, int len, BiTree &t)
 72 {
 73     if (len <= 0) return;
 74     char *p = NULL, *q = NULL;
 75     int i = 0;                // i 表示根节点在中序中的位置
 76     t = (BiTree)malloc(sizeof(BiTNode));
 77     t->data = pos[len-1];     // 确定根节点
 78     t->leftChild = NULL;
 79     t->rightChild = NULL;
 80     while (i < len)
 81     {
 82         if (*(in + i) == pos[len-1])
 83             break;
 84         ++i;
 85     }
 86     p = in;                
 87     q = pos;
 88     In_Pos_Create(p, q, i, t->leftChild);
 89     p = in + i + 1;           
 90     q = pos + i;
 91     In_Pos_Create(p, q, len-i-1, t->rightChild);
 92 }
 93 // 由先序序列创建二叉树
 94 void CreatePre(BiTree &t, TElemType *&str)
 95 {
 96     if (*str == '#')
 97     {
 98         t = NULL;
 99     }
100     else
101     {
102         t = (BiTNode *)malloc(sizeof(BiTNode));
103         t->data = *str;
104         CreatePre(t->leftChild, ++str);
105         CreatePre(t->rightChild, ++str);
106     }
107 }
108 
109 void PrintAll(BiTree& t)
110 {
111     PreOrder(t);
112     printf("
");
113     InOrder(t);
114     printf("
");
115     PostOrder(t);
116     printf("
");
117 }
118 
119 void main()
120 {
121     printf("由先序序列创建二叉树mytree: 
");
122     TElemType *buff = "ABC##DE##F##G#H##";
123     BiTree mytree;
124     InitTree(mytree);
125     CreatePre(mytree, buff);
126     printf("Print  mytree: 
");
127     PrintAll(mytree);
128 
129     char *pbuff = "ABCDEFGH";
130     char *ibuff = "CBEDFAGH";
131     char *tbuff = "CEFDBHGA";
132     BiTree  mypretree;
133     InitTree(mypretree);
134     printf("由先序和中序创建二叉树mypretree: 
");
135     Pre_In_Create(pbuff, ibuff, 8, mypretree);
136     printf("Print  mypretree: 
");
137     PrintAll(mypretree);
138 
139     BiTree  mypostree;
140     InitTree(mypostree);
141     printf("由中序和后序创建二叉树mypostree: 
");
142     In_Pos_Create(ibuff, tbuff, 8, mypostree);
143     printf("Print  mypostree: 
");
144     PrintAll(mypostree);
145 }
View Code

(8)线索二叉树

1. 为什么要线索化二叉树?

遍历二叉树除了设栈,要么就用递归进行。有没有其它更好的方式呢?

遍历二叉树实质上是对一个非线性结构进行线性化操作的过程。

那么既然是线性化的过程能否先像线性链表那样把树结构进行线性化?

当以二叉链表作为存储结构时,只能找到结点的左右孩子信息,并不能找到结点在任一序列中的前驱和后继信息。

所以为了方便于遍历,只有通过在每个结点上增加两个指针域,分别指示结点在任一次序遍历时得到的前驱和后继。

指向结点的前驱和后继的指针叫做线索。

加上线索的二叉树称为线索二叉树。

对二叉树以某种次序(先序,中序,后序)遍历使其变为线索二叉树的过程叫做线索化。

所谓穿线二叉树,即在一般二叉树的基础上,对每个结点进行考察:

若其左子树非空,则其左指针不变,仍指向左子女;

若其左子树为空,则让其左指针指向某种遍历顺序下该结点的前驱;

若其右子树非空,则其右指针不变,仍指向右子女;

若其右子树为空,则让其右指针指向某种遍历顺序下该结点的后继。

线索化二叉树其实通俗点说:就好像要从某个地方要到另一个地方去,以前咱是边走边找路。

而现在是根据以前“经验”(某种次序)在路上做好标记,以后你不管走多少次,只要按照标线走就行,不需要再每次都边走边找路了。

线索化的过程需要用到遍历算法,一旦线索建立后,在此结构上遍历就可以不用递归、也不用栈了,实现更加容易

总而言之:

线索化二叉树相当于是按照某种遍历的次序,提前把遍历的路径给做好标记,以后再遍历的时候就会方便很多,所以要线索化二叉树。

线索二叉树的图示:

切记:

 有n个节点的二叉链表中必定存在n+1个空链域

 在一棵有n个节点度为k的树中必有n(k-1)+1个空链域

【4】树和森林

(1)树的存储结构

1. 双亲表示法

由于树中的每个结点都有唯一的一个双亲结点,所以可用一组连续的存储空间(一维数组)存储树中的各个结点。

数组中的一个元素表示树中的一个结点,每个结点含两个域,数据域存放结点本身信息,双亲域指示本结点的双亲结点在数组中位置。

2. 孩子表示法

孩子表示法又分为 多重链表法 和 孩子链表表示法。

a. 多重链表法 指每个结点包括一个结点信息域和多个指针域,每个指针域指向该结点的一个孩子结点,通过各个指针域值反映出树中各结点之间的逻辑关系。

在这种表示法中,树中每个结点有多个指针域,从而形成了多条链表。

由于每个结点的孩子个数没有限制,各结点的度数又各异,所以操作不容易实现,可能会造成存储空间的浪费。

b. 孩子链表法与双亲表示法相反,便于查找树中某结点的孩子,由某结点的指针域便可实现,它的主体是一个与结点个数一样大小的一维数组。

数组的每一个元素由两个域组成,一个域用来存放结点信息,另一个用来存放指针,该指针指向由该结点孩子组成的单链表的首位置。

单链表的结构也由两个域组成,一个存放孩子结点在一维数组中的序号,另一个是指针域,指向下一个孩子。

孩子表示法方便了有关孩子的操作,但有时为了便于找到双亲,可以将双亲表示法和孩子表示法相结合:

即增加一个域,存储该结点双亲结点在数组中的序号。这种存储结构称为代双亲的孩子链表。

3. 左孩子右兄弟表示法

孩子兄弟表示法又称二叉树表示法,这是一种常用的存储结构。

它用二叉链表作为树的存储结构,链表中每个结点的两个指针域分别指向其第一个孩子结点和下一个兄弟结点。

(2) 树与二叉树的对应关系

(3) 森林与二叉树的对应关系

(4) 二叉树转换为树

(5) 树转换为二叉树

(6) 二叉树转换为森林

(7) 森林转换为二叉树

【5】霍夫曼树

关于霍夫曼树请参见随笔《赫夫曼树

 

原文地址:https://www.cnblogs.com/Braveliu/p/3449321.html