中序线索二叉树

线索化二叉树

 #include <iostream>
using namespace std;
struct ThreadNode{
char data;
ThreadNode *lchild,*rchild;
int ltag=0,rtag=0;               //需要初始化为0,不然会出现乱码现象而不是默认为0 
};
ThreadNode *pre=NULL;
ThreadNode* creatThreadNode(char a[],char b[],int n){//先序和中序构造二叉树
 ThreadNode *p=new ThreadNode;                            //根  左  右         
 p->data=a[0];                                    //左  根  右
 int i=0;
 /*for(;;)
 {

  if(a[n]==NULL)        //指针才能判断这个为NULL
  break;
  else
  n++;
 }*/
 for(;;)                    //计算左子树的个数
 {

  if(a[0]==b[i])
  break;
  else
  i++;
 }
 if(i!=0){             //如果有左子树递归
  char a1[i],b1[i];
  for(int j=0;j<i;j++)
  {
   a1[j]=a[j+1];
   b1[j]=b[j];
  }
   p->lchild=creatThreadNode(a1,b1,i);
 }
 else             //没有左子树为NULL
  p->lchild=NULL;
 if(n!=i+1){
  char a2[n-i-1],b2[n-i-1];
  for(int j=0;j<n-i-1;j++)
  {
   a2[j]=a[j+i+1];
   b2[j]=b[j+i+1];
  }
  p->rchild=creatThreadNode(a2,b2,n-i-1);
 }
 else
 p->rchild=NULL;
 return p;
}


//利用visit的用处是:如果用先序线索化二叉树的话好加判断if(T->ltag==0)//T->lchild 不是前驱线索 
void visit(ThreadNode *q)    //每次循环设置   首为空  结点前驱的后继和结点的前驱   尾为空
{
if(q->lchild==NULL){           //首为空 +  结点的前驱
q->lchild=pre;
q->ltag=1;
}
if(pre!=NULL&&pre->rchild==NULL)      //pre!=NULL是为了排除pre初始为NULL的情况 
{ //尾为空 + 结点前驱的后继
pre->rchild=q;
pre->rtag=1;
}
pre=q;
}
void InThread(ThreadNode *T)
{
if(T==NULL)
return;
InThread(T->lchild);
visit(T);
/*if(T->lchild==NULL){           //首为空 +  结点的前驱
T->lchild=pre;
T->ltag=1;
}
if(pre!=NULL&&pre->rchild==NULL)      //pre!=NULL是为了排除pre初始为NULL的情况 
{ //尾为空 + 结点前驱的后继
pre->rchild=T;
pre->rtag=1;
}
pre=T;*/
InThread(T->rchild);
}
//CreateInThread的用处是:让最后一个右子树的右tag=1
void CreateInThread(ThreadNode *T)         //中序线索化 
{
if(T!=NULL) //传递root
{
InThread(T);
}
if(pre->rchild==NULL)           //让最后一个右子树的右tag=1
{
pre->rtag=1;
}
}
//先序和后序线索化      和中序一样但是加点条件进入左子树用ltag变量,不然会无限循环
//中序线索化 左 根 右     先序线索化 根 (条件:T->ltag==0)左 右      后序线索化   左 右 根 (不用条件)


ThreadNode* GetNext(ThreadNode *p)  //求后继结点
{
if(p->rtag==1)         //如果右tag=1它的右孩子就是它的后继 
return p->rchild;        
p=p->rchild;            //否则就是它的右子树的最左下方的结点 
while(p->ltag==0)
p=p->lchild;
return p;
}
ThreadNode* GetPrev(ThreadNode *p)   //求前驱结点  
{ 
if(p->ltag==1)           //同上 
return p->lchild;
p=p->lchild;
while(p->rtag==0)
p=p->rchild;
return p;
}
void InOrder(ThreadNode *p)   //利用线索二叉树进行中序遍历 
{
while(p->ltag==0)
{
p=p->lchild;
}
while(p!=NULL)
{
cout<<p->data<<" ";
p=GetNext(p);
}
} 
ThreadNode* GetParent(ThreadNode *p)           //寻找父结点 
{
if(p==NULL)
return NULL; 
ThreadNode * parent;
parent=p;
while(parent->rtag==0)                 //1.如果p是父结点的左子树,寻找父结点方法:p的最右子树的后继结点 
{
parent=parent->rchild;              //找到p的最右下方的结点 
}
parent=parent->rchild;                 //p的最右下方的结点的后继结点
if(parent->lchild==p)                  //判断假设是否成立 
return parent;
while(parent->ltag==0)                 //2.如果p是父结点的右子树,寻找父结点方法:p的最左子树的前驱结点 
{
parent=parent->lchild;              //找到p的最左下方的结点 
}
parent=parent->lchild;                 //p的最左下方的结点的前驱结点
if(parent->rchild==p)
return parent;
}
int main(){
ThreadNode *root;
char a[9]={'A','B','H','F','D','E','C','K','G'},b[9]={'H','B','D','F','A','E','K','C','G'};//p120 先+中 
  root=creatThreadNode(a,b,9);
 
 

 //线索化二叉树 
CreateInThread(root);
 
// 获得前驱和后继结点 
/*cout<<GetNext(root)->data<<endl;
  cout<<GetPrev(root)->data<<endl;*/
 
//利用线索遍历二叉树  中序 
InOrder(root);
  cout<<endl;
 
 //寻找为什么不给ltag和rtag赋初值就会少一个K输出,原因:C的ltag出现乱码 
/*cout<<"E的rtag:"<<root->rchild->rtag<<endl;      
cout<<"E的后驱结点数据:"<<GetNext(root->rchild)->data<<endl;
cout<<"C的ltag:"<<root->rchild->rchild->ltag<<endl;*/

//寻找父结点 
cout<<GetParent(root->lchild->lchild)->data<<endl; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值