线索化二叉树的构建与先序,中序遍历(C++版)

贴出学习C++数据结构线索化二叉树的过程,

方便和我一样的新手进行测试和学习

同时欢迎各位大神纠正。

不同与普通二叉树的地方会用背景色填充

//BinTreeNode_Thr.h

 1 enum PointTag
 2 {Link,Thread};
 3
 4 template<typename ElemType>
 5 struct BinTreeNode
 6 {
 7     ElemType data;                     //数据元素
 8     PointTag LTag,RTag;                 //左标志,右标志
 9     BinTreeNode<ElemType> *leftChild;  //指向左孩子的指针
10     BinTreeNode<ElemType> *rightChild; //指向右孩子的指针
11     //函数构造
12     BinTreeNode();
13     BinTreeNode(const ElemType &val,
14         BinTreeNode<ElemType> *lChild=NULL,
15         BinTreeNode<ElemType> *rChild=NULL);
16     BinTreeNode<ElemType> &operator =(const BinTreeNode<ElemType> &copy);
17 };
18
19 template<typename ElemType>
20 BinTreeNode<ElemType>::BinTreeNode()
21 {
22     leftChild=rightChild=NULL;
23     LTag=RTag=Link;               //此处初始化为Link,即存在孩子
24 }
25
26 template<typename ElemType>
27 BinTreeNode<ElemType>::BinTreeNode(const ElemType &val,
28                         BinTreeNode<ElemType> *lChild,
29                         BinTreeNode<ElemType> *rChild)
30 {
31     data=val;
32     LTag=RTag=Link;               //初始化为Link
33     leftChild=lChild;
34     rightChild=rChild;
35 }
36
37 template<typename ElemType>
38 BinTreeNode<ElemType> &BinTreeNode<ElemType>::operator =(const BinTreeNode<ElemType> &copy)
39 {
40     data=copy.data;
41     leftChild=copy.leftChild;
42     rightChild=copy.leftChild;
43     LTag=copy.LTag;
44     RTag=copy.RTag;
45 }

//BinaryTree_Thr.h

  1 #include"BinTreeNode_Thr.h"
  2 template<typename ElemType>
  3 class BinaryTree_Thr
  4 {
  5 protected:
  6     //数据成员
  7     BinTreeNode<ElemType> *root;
  8     //辅助函数
  9     BinTreeNode<ElemType> *CopyTreeHelp(const BinTreeNode<ElemType> *r);//复制二叉树
 10     void DestroyHelp(BinTreeNode<ElemType> *&r);//销毁r为根的二叉树
 11     void PreThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre);   //先序线索化
 12     void InThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre);   //中序线索化
 13     void CreateBTreeHelp(BinTreeNode<ElemType> *&r,ElemType pre[],ElemType in[],int,int,int,int);//用中序和先序序列构造树
 14 public:
 15     BinaryTree_Thr(){root=NULL}//无参构造
 16     BinaryTree_Thr(BinTreeNode<ElemType> *r){ root=r;}//建立以r为根的二叉树
 17     virtual ~BinaryTree_Thr();//有指针自定义虚构,且用虚虚构
 18     BinaryTree_Thr<ElemType> &CreateBTree(ElemType pre[],ElemType in[],int n); //构造树
 19     void PreTreading();//先序线索化
 20     void InTreading();//中序线索化
 21     void PreOrderTraverse_Thr(void (*visit) (const ElemType &))const;                       //先序遍历
 22     void InOrderTraverse_Thr(void (*visit) (const ElemType &))const;                       //中序遍历
 23     void LevelOrder(void (*visit) (const ElemType &))const;
 24     BinaryTree_Thr<ElemType> &operator =(const BinaryTree_Thr<ElemType> &copy);//重载赋值运算符
 25 };

 26 //Copy
 27 template<typename ElemType>
 28 BinTreeNode<ElemType> *BinaryTree_Thr<ElemType>::CopyTreeHelp(const BinTreeNode<ElemType> *r)
 29 {
 30     BinTreeNode<ElemType> *cur;
 31     if(r==NULL)   cur=NULL;
 32     else
 33     {
 34         BinTreeNode<ElemType> *lChild=CopyTreeHelp(r->leftChild);//复制左子树
 35         BinTreeNode<ElemType> *rChild=CopyTreeHelp(r->rightChild);//复制右子树
 36         cur=new BinTreeNode<ElemType>(r->data,lChild,rChild);
 37         //复制根节点
 38     }
 39     return cur;
 40 }
 41
 42 template<typename ElemType>
 43 void BinaryTree_Thr<ElemType>::InThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre)//中序遍历
 44     {
 45     if(p)
 46         {
 47             if(p->LTag==Link)
 48                 InThreadingHelp(p->leftChild,pre);    //线索化左子树.
 49             if(!p->leftChild)                 //左孩子空
 50             {
 51                 p->LTag=Thread;
 52                 p->leftChild=pre;
 53             }
 54             if(!pre->rightChild)             //前驱 的右孩子空
 55             {
 56                 pre->RTag=Thread;
 57                 pre->rightChild=p;
 58             }
 59             pre=p;
 60             if(p->RTag==Link)
 61                 InThreadingHelp(p->rightChild,pre);  //线索化右子树
 62         }
 63
 64     }
 65
 66 template<typename ElemType>
 67 void BinaryTree_Thr<ElemType>::PreThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre)//先序遍历
 68     {
 69     if(p)
 70         {
 71             if(!p->leftChild)                 //左孩子空
 72             {
 73                 p->LTag=Thread;
 74                 p->leftChild=pre;
 75             }
 76             if(!pre->rightChild)             //前驱 的右孩子空
 77             {
 78                 pre->RTag=Thread;
 79                 pre->rightChild=p;
 80             }
 81             pre=p;
 82             if(p->LTag==Link)
 83                 PreThreadingHelp(p->leftChild,pre);    //线索化左子树.
 84             if(p->RTag==Link)
 85                 PreThreadingHelp(p->rightChild,pre);  //线索化右子树
 86         }
 87
 88     }
 89
 90 template<typename ElemType>
 91 void BinaryTree_Thr<ElemType>::DestroyHelp(BinTreeNode<ElemType> *&r)
 92 {
 93     if(r!=NULL)
 94     {
 95         if(r->LTag==Link)
 96             DestroyHelp(r->leftChild);
 97         if(r->RTag==Link)
 98             DestroyHelp(r->rightChild);
 99         delete r;
100         r=NULL;
101     }
102 }
103
104 //虚构
105 template<typename ElemType>
106 BinaryTree_Thr<ElemType>::~BinaryTree_Thr()
107 {
108     DestroyHelp(root);
109 }
110
111 template<typename ElemType>
112 //Thr为头节点,T为根.
113 void BinaryTree_Thr<ElemType>::InTreading()
114 {
115     BinTreeNode<ElemType> *pre=root;
116     InThreadingHelp(root,pre);    //中序线索化
117     if(pre->rightChild==NULL)
118         pre->RTag=Thread;       //处理最后一个节点
119 }
120
121 template<typename ElemType>
122 void BinaryTree_Thr<ElemType>::PreTreading()
123 {
124     BinTreeNode<ElemType> *pre=root;
125     PreThreadingHelp(root,pre);    //先序线索化
126     if(pre->rightChild==NULL)
127         pre->RTag=Thread;       //处理最后一个节点
128 }
129
130 template<typename ElemType>
131 void print(const ElemType &e )
132 {
133     cout<<e<<" ";
134 }
135
136 template<typename ElemType>
137 void BinaryTree_Thr<ElemType>::InOrderTraverse_Thr(void (*visit) (const ElemType &))const
138 {
139     visit=print;
140     if(root!=NULL){
141         BinTreeNode<ElemType> *p=root;            //p指向根
142         while(p->LTag==Link)  p=p->leftChild;     //左走至最左下角
143         while(p)
144         {
145             (*visit)(p->data);       //访问结点元素
146             if(p->RTag==Thread)      //右孩子为线索,则p指向后继
147             {
148                 p=p->rightChild;
149             }
150             else    //右孩子存在
151             {
152                 p=p->rightChild;     //遍历右孩子
153                 while(p->LTag==Link)
154                     p=p->leftChild;
155             }
156         }
157     }
158 }
159
160 template<typename ElemType>
161 void BinaryTree_Thr<ElemType>::PreOrderTraverse_Thr(void (*visit) (const ElemType &))const
162 {
163     visit=print;
164     if(root!=NULL){
165         BinTreeNode<ElemType> *p=root;        //p指向根
166         while(p)
167         {
168             (*visit)(p->data);
169             if(p->RTag==Thread)
170                 p=p->rightChild;
171             else
172             {
173                 if(p->LTag==Link)
174                     p=p->leftChild;
175                 else
176                     p=p->rightChild;
177             }
178         }
179     }
180 }
181
182 template<typename ElemType>
183 void BinaryTree_Thr<ElemType>::CreateBTreeHelp(BinTreeNode<ElemType> *&r,
184                                            ElemType pre[],ElemType in[],
185                                            int preLeft,int preRight,int inLeft,int inRight)
186
187 {
188     if(preLeft>preRight||inLeft>inRight)
189         r=NULL;
190     else
191     {
192         r=new BinTreeNode<ElemType>(pre[preLeft]);//生成根结点
193         int mid=inLeft;
194         while(in[mid]!=pre[preLeft])
195             mid++;
196         CreateBTreeHelp(r->leftChild,pre,in,preLeft+1,preLeft+mid-inLeft,inLeft,mid-1);        //这里如果不懂建议自己画图手工实现一遍。
197         CreateBTreeHelp(r->rightChild,pre,in,preLeft+mid-inLeft+1,preRight,mid+1,inRight);
198     }
199 }
200
201 template<typename ElemType>
202 //构造树
203 BinaryTree_Thr<ElemType>& BinaryTree_Thr<ElemType>::CreateBTree(ElemType pre[],ElemType in[],int n)
204 {
205     BinTreeNode<ElemType> *r;   //根
206     CreateBTreeHelp(r,pre,in,0,n-1,0,n-1);
207     //return BinaryTree<ElemType>(r);//,不能这么返回,Error:不应该返回局部变量的地址
208     *this = BinaryTree_Thr<ElemType>(r);
209     return *this;
210 }
211
212 #include<queue>
213 template<typename ElemType>
214 void BinaryTree_Thr<ElemType>::LevelOrder(void (*visit) (const ElemType &))const
215 {    //队列实现
216     visit=print;
217     queue<BinTreeNode<ElemType> *> q;
218     BinTreeNode<ElemType> *t=root;
219     if(t!=NULL) q.push(t);                //根非空,入队
220     while(!q.empty())                //队不空
221     {
222         t=q.front();
223         q.pop();                    //出队
224         (*visit)(t->data);          //一层一层进行遍历,无法理解还是自己画图实现一遍
225         if(t->leftChild)
226             q.push(t->leftChild);  //遍历左孩子
227         if(t->rightChild)
228             q.push(t->rightChild); //遍历右孩子
229     }
230
231 }
232
233 //operator =
234 template<typename ElemType>
235 BinaryTree_Thr<ElemType> &BinaryTree_Thr<ElemType>::operator=(const BinaryTree_Thr<ElemType> &copy)
236 {
237     if(&copy!=this)
238     {
239         DestroyHelp(root);
240         root=CopyTreeHelp(copy.root);
241     }
242     return *this;
243 }
时间: 2024-10-13 12:52:30

线索化二叉树的构建与先序,中序遍历(C++版)的相关文章

数据结构与算法---线索化二叉树(Threaded BinaryTree)

先看一个问题 将数列 {1, 3, 6, 8, 10, 14  } 构建成一颗二叉树 问题分析: 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 } 但是 6, 8, 10, 14 这几个节点的 左右指针,并没有完全的利用上. 如果我们希望充分的利用 各个节点的左右指针, 让各个节点可以指向自己的前后节点,怎么办? 解决方案-线索二叉树 线索二叉树基本介绍 1.n个结点的二叉链表中含有n+1  [公式 2n-(n-1)=n+1] 个空指针域.利用二叉链表中的空

java实现线索化二叉树的前序、中序、后续的遍历(完整代码)

java实现线索化二叉树的前序.中序.后续的遍历 比如创建一个二叉树 1 / 3 6 / \ / 8 10 14 线索化二叉树几个概念: n个节点的二叉链表中含有n+1 [公式2n-(n-1)=n+1]个空指针域.利用二叉链表中的空指针域,存放指向该节点在某种遍历次序下的前驱和后继节点的指针(这种附加指针成为线索).如下面的就是6+1=7个空指针域 (8,10,14各有连个指针没有指向 6有一个) 加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树.分为前序线索二叉树.中序线索二叉树.

遍历及线索化二叉树

①二叉树的遍历是指从根结点开始,按照某种次序依次访问二叉树中的所有结点 ②二叉树遍历方式(所谓前序.中序.后序,是对根结点来说的) 1.前序遍历 2.中序遍历 3.后续遍历 4.层次遍历 前序遍历:1.2.4.8.9.5.10.3.6.7 中序遍历:8.4.9.2.10.5.1.6.3.7 后序遍历:8.9.4.10.5.2.6.7.3.1 层次遍历:1.2.3.4.5.6.7.8.9.10 ③线索化二叉树指的是将二叉树中的结点进行逻辑意义上的"重排列",使其可以以线性的方式访问每一个

树五:线索化二叉树

线索化二叉树: 线索化二叉树指的是将二叉树中的结点进行逻辑意义上的“重排列”,使其可以线性的方式访问每一个结点. 二叉树线索化后每个结点都有一个线性下标,通过这个下标可以快速访问结点,而不需要遍历二叉树.

数据--第37课 - 线索化二叉树

第37课 - 线索化二叉树 1. 问题 在一些项目中需要频繁的遍历二叉树,但是二叉树的遍历比单链表的遍历复杂多了,并且递归总是会后额外的开销. 2. 线索化二叉树 线索化二叉树指的是将二叉树中的结点进行逻辑意义上的“重新排列”,使其可以线性的方式访问每一个结点. 二叉树线索化后每个结点都有一个线性下标,用过这个下标可以快速访问结点,而不需要遍历二叉树. 3. 方法1 利用结点中的空指针,使其指向后继结点. 算法思想: 初始化位置指针:p = NULL: 前序遍历二叉树: 若p不为空,将p->le

中序线索化二叉树

中序线索化二叉树 1 void Tree::_inTree(Node * root, Node * &pre) { 2 if (root == NULL) { // 结点为空, 1:二叉树为空 2:已到达右子树的最后一个右结点的 rchild 3 return; 4 } 5 _inTree(root->lchild, pre); // 到达当前结点的左子树的底部左结点 6 if (root->lchild == NULL) { 7 root->ltag = nChild; //

数据结构例程——线索化二叉树(中序)

本文是数据结构基础系列(6):树和二叉树中第14课时线索二叉树的例程. #include <stdio.h> #include <malloc.h> #define MaxSize 100 typedef char ElemType; typedef struct node { ElemType data; int ltag,rtag; //增加的线索标记 struct node *lchild; struct node *rchild; } TBTNode; void Creat

【数据结构】线索化二叉树中序线索化的递归写法和非递归写法

二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历.用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继. 为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息.所以引入了线索化二叉树.下面我们讲一下线索化二叉树中序线索化的两种实现方法: (1).递归实现中序线索化二叉树 首先我们先看一下线索化二叉树的结构 enum PointerTag{ THREAD, LINK 

线索化二叉树

二叉树的遍历运算是将二叉树中节点按一定规律线性化的过程,当二叉链表作为存储结构时,只能找到节点的左.右孩子信息,而不能直接得到节点在遍历序列中的前驱和后继信息.线索化二叉树能够解决这样的问题,将二叉链表中的空指针域填上相应节点的遍历前驱或后继节点的地址,而前驱和后继的地址只能在动态的遍历过程中才能得到.可以按照不同的遍历次序进行线索化,先序遍历.遍历过程中的节点的前驱.后继信息保存下来.下面是线索化二叉树节点结构: 其中,_left和_right表示节点的左.右孩子,_leftTag和_righ