贴出学习C++数据结构线索化二叉树的过程,
方便和我一样的新手进行测试和学习
同时欢迎各位大神纠正。
不同与普通二叉树的地方会用背景色填充
//BinTreeNode_Thr.h
enum PointTag
{Link,Thread}; template<typename ElemType>
struct BinTreeNode
{
ElemType data; //数据元素
PointTag LTag,RTag; //左标志,右标志
BinTreeNode<ElemType> *leftChild; //指向左孩子的指针
BinTreeNode<ElemType> *rightChild; //指向右孩子的指针
//函数构造
BinTreeNode();
BinTreeNode(const ElemType &val,
BinTreeNode<ElemType> *lChild=NULL,
BinTreeNode<ElemType> *rChild=NULL);
BinTreeNode<ElemType> &operator =(const BinTreeNode<ElemType> ©);
}; template<typename ElemType>
BinTreeNode<ElemType>::BinTreeNode()
{
leftChild=rightChild=NULL;
LTag=RTag=Link; //此处初始化为Link,即存在孩子
} template<typename ElemType>
BinTreeNode<ElemType>::BinTreeNode(const ElemType &val,
BinTreeNode<ElemType> *lChild,
BinTreeNode<ElemType> *rChild)
{
data=val;
LTag=RTag=Link; //初始化为Link
leftChild=lChild;
rightChild=rChild;
} template<typename ElemType>
BinTreeNode<ElemType> &BinTreeNode<ElemType>::operator =(const BinTreeNode<ElemType> ©)
{
data=copy.data;
leftChild=copy.leftChild;
rightChild=copy.leftChild;
LTag=copy.LTag;
RTag=copy.RTag;
}
//BinaryTree_Thr.h
#include"BinTreeNode_Thr.h"
template<typename ElemType>
class BinaryTree_Thr
{
protected:
//数据成员
BinTreeNode<ElemType> *root;
//辅助函数
BinTreeNode<ElemType> *CopyTreeHelp(const BinTreeNode<ElemType> *r);//复制二叉树
void DestroyHelp(BinTreeNode<ElemType> *&r);//销毁r为根的二叉树
void PreThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre); //先序线索化
void InThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre); //中序线索化
void CreateBTreeHelp(BinTreeNode<ElemType> *&r,ElemType pre[],ElemType in[],int,int,int,int);//用中序和先序序列构造树
public:
BinaryTree_Thr(){root=NULL}//无参构造
BinaryTree_Thr(BinTreeNode<ElemType> *r){ root=r;}//建立以r为根的二叉树
virtual ~BinaryTree_Thr();//有指针自定义虚构,且用虚虚构
BinaryTree_Thr<ElemType> &CreateBTree(ElemType pre[],ElemType in[],int n); //构造树
void PreTreading();//先序线索化
void InTreading();//中序线索化
void PreOrderTraverse_Thr(void (*visit) (const ElemType &))const; //先序遍历
void InOrderTraverse_Thr(void (*visit) (const ElemType &))const; //中序遍历
void LevelOrder(void (*visit) (const ElemType &))const;
BinaryTree_Thr<ElemType> &operator =(const BinaryTree_Thr<ElemType> ©);//重载赋值运算符
}; //Copy
template<typename ElemType>
BinTreeNode<ElemType> *BinaryTree_Thr<ElemType>::CopyTreeHelp(const BinTreeNode<ElemType> *r)
{
BinTreeNode<ElemType> *cur;
if(r==NULL) cur=NULL;
else
{
BinTreeNode<ElemType> *lChild=CopyTreeHelp(r->leftChild);//复制左子树
BinTreeNode<ElemType> *rChild=CopyTreeHelp(r->rightChild);//复制右子树
cur=new BinTreeNode<ElemType>(r->data,lChild,rChild);
//复制根节点
}
return cur;
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::InThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre)//中序遍历
{
if(p)
{
if(p->LTag==Link)
InThreadingHelp(p->leftChild,pre); //线索化左子树.
if(!p->leftChild) //左孩子空
{
p->LTag=Thread;
p->leftChild=pre;
}
if(!pre->rightChild) //前驱 的右孩子空
{
pre->RTag=Thread;
pre->rightChild=p;
}
pre=p;
if(p->RTag==Link)
InThreadingHelp(p->rightChild,pre); //线索化右子树
} } template<typename ElemType>
void BinaryTree_Thr<ElemType>::PreThreadingHelp(BinTreeNode<ElemType> *p,BinTreeNode<ElemType> *&pre)//先序遍历
{
if(p)
{
if(!p->leftChild) //左孩子空
{
p->LTag=Thread;
p->leftChild=pre;
}
if(!pre->rightChild) //前驱 的右孩子空
{
pre->RTag=Thread;
pre->rightChild=p;
}
pre=p;
if(p->LTag==Link)
PreThreadingHelp(p->leftChild,pre); //线索化左子树.
if(p->RTag==Link)
PreThreadingHelp(p->rightChild,pre); //线索化右子树
} } template<typename ElemType>
void BinaryTree_Thr<ElemType>::DestroyHelp(BinTreeNode<ElemType> *&r)
{
if(r!=NULL)
{
if(r->LTag==Link)
DestroyHelp(r->leftChild);
if(r->RTag==Link)
DestroyHelp(r->rightChild);
delete r;
r=NULL;
}
} //虚构
template<typename ElemType>
BinaryTree_Thr<ElemType>::~BinaryTree_Thr()
{
DestroyHelp(root);
} template<typename ElemType>
//Thr为头节点,T为根.
void BinaryTree_Thr<ElemType>::InTreading()
{
BinTreeNode<ElemType> *pre=root;
InThreadingHelp(root,pre); //中序线索化
if(pre->rightChild==NULL)
pre->RTag=Thread; //处理最后一个节点
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::PreTreading()
{
BinTreeNode<ElemType> *pre=root;
PreThreadingHelp(root,pre); //先序线索化
if(pre->rightChild==NULL)
pre->RTag=Thread; //处理最后一个节点
} template<typename ElemType>
void print(const ElemType &e )
{
cout<<e<<" ";
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::InOrderTraverse_Thr(void (*visit) (const ElemType &))const
{
visit=print;
if(root!=NULL){
BinTreeNode<ElemType> *p=root; //p指向根
while(p->LTag==Link) p=p->leftChild; //左走至最左下角
while(p)
{
(*visit)(p->data); //访问结点元素
if(p->RTag==Thread) //右孩子为线索,则p指向后继
{
p=p->rightChild;
}
else //右孩子存在
{
p=p->rightChild; //遍历右孩子
while(p->LTag==Link)
p=p->leftChild;
}
}
}
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::PreOrderTraverse_Thr(void (*visit) (const ElemType &))const
{
visit=print;
if(root!=NULL){
BinTreeNode<ElemType> *p=root; //p指向根
while(p)
{
(*visit)(p->data);
if(p->RTag==Thread)
p=p->rightChild;
else
{
if(p->LTag==Link)
p=p->leftChild;
else
p=p->rightChild;
}
}
}
} template<typename ElemType>
void BinaryTree_Thr<ElemType>::CreateBTreeHelp(BinTreeNode<ElemType> *&r,
ElemType pre[],ElemType in[],
int preLeft,int preRight,int inLeft,int inRight) {
if(preLeft>preRight||inLeft>inRight)
r=NULL;
else
{
r=new BinTreeNode<ElemType>(pre[preLeft]);//生成根结点
int mid=inLeft;
while(in[mid]!=pre[preLeft])
mid++;
CreateBTreeHelp(r->leftChild,pre,in,preLeft+,preLeft+mid-inLeft,inLeft,mid-); //这里如果不懂建议自己画图手工实现一遍。
CreateBTreeHelp(r->rightChild,pre,in,preLeft+mid-inLeft+,preRight,mid+,inRight);
}
} template<typename ElemType>
//构造树
BinaryTree_Thr<ElemType>& BinaryTree_Thr<ElemType>::CreateBTree(ElemType pre[],ElemType in[],int n)
{
BinTreeNode<ElemType> *r; //根
CreateBTreeHelp(r,pre,in,,n-,,n-);
//return BinaryTree<ElemType>(r);//,不能这么返回,Error:不应该返回局部变量的地址
*this = BinaryTree_Thr<ElemType>(r);
return *this;
} #include<queue>
template<typename ElemType>
void BinaryTree_Thr<ElemType>::LevelOrder(void (*visit) (const ElemType &))const
{ //队列实现
visit=print;
queue<BinTreeNode<ElemType> *> q;
BinTreeNode<ElemType> *t=root;
if(t!=NULL) q.push(t); //根非空,入队
while(!q.empty()) //队不空
{
t=q.front();
q.pop(); //出队
(*visit)(t->data); //一层一层进行遍历,无法理解还是自己画图实现一遍
if(t->leftChild)
q.push(t->leftChild); //遍历左孩子
if(t->rightChild)
q.push(t->rightChild); //遍历右孩子
} } //operator =
template<typename ElemType>
BinaryTree_Thr<ElemType> &BinaryTree_Thr<ElemType>::operator=(const BinaryTree_Thr<ElemType> ©)
{
if(©!=this)
{
DestroyHelp(root);
root=CopyTreeHelp(copy.root);
}
return *this;
}