遍历二叉树和线索二叉树

中序线索二叉树

在这里插入图片描述
实现代码如下

#include <iostream>
#include <stdlib.h>
#include <stack>
#include <cstring>
#include <cstdio>
using namespace std;
enum PointerTag{Link, Thread};//指针标志,Link==0:指针,Thread==1:线索 
typedef struct BiThTree
{
    char data;
    struct BiThTree *lchild, *rchild;
    PointerTag LTag, RTag;
}BiThTree;
BiThTree *pre;   //全局变量,用于二叉树的线索化 
int InTread(BiThTree *T) //中序线索建立 内
{
    BiThTree *p;
	p=T; 
	if(p!= NULL)
    {
        InTread(p->lchild);//左子树线索化 
        if(p->lchild == NULL)//建立当前结点的前驱线索 
		{ 
		   p->LTag = Thread; 
		   p->lchild = pre;
		}
        else
		{ 
		   p->LTag = Link;
		}
        if(pre->rchild == NULL)//建立前驱节点的后继线索 
		{ 
		   pre->RTag = Thread; 
		   pre->rchild = p;
		}
        else
		{ 
		   p->RTag = Link;
		}
        pre = p;
        InTread(p->rchild);
    }
    return 0;
}
BiThTree *CreatThread(BiThTree *T)     //中序线索化二叉树
{    //中序遍历二叉树b,并将其中序线索化,root指向头结点
     BiThTree  *root;
     root=(BiThTree *)malloc(sizeof(BiThTree));        //创建头结点
     root->LTag=Link;                          //头结点有左孩子,若树非空,则其左孩子为树根
     root->RTag=Thread;                         //头结点的右孩子指针为右线索
     root->rchild=T;                      //头结点的右孩子指针指向根结点
     if (T==NULL)  root->lchild=root;   //若树为空,则左指针也指向自己
     else
     {     
	      root->lchild=T;                        //头结点的左孩子指向根
	      pre=root;            //pre是*p的前驱结点,供加线索用,pre初值指向头结点
	      InTread(T);       //调用Thread()算法,对以b为根的二叉树进行中序线索化
	      pre->rchild=root;                   //Thread()算法结束后,pre为最右结点,
                                                                //pre的右线索指向头结点
	      pre->RTag=Thread;
	      root->rchild=pre;    	      //头结点的右线索指向pre
     }
     return root;
}
void creatBinTree(char*s,BiThTree *T)
{
   //int i;
   bool isRight=false;
   stack<BiThTree*>s1;
   stack<char>s2;
   BiThTree *p,*temp;
   T->data=s[0];
   T->lchild=NULL;
   T->rchild=NULL;
   s1.push(T);
   int i=1;
   while(i<strlen(s))
   {
      if(s[i]=='(')
	  {
	     s2.push(s[i]);
		 isRight=false;
	  }
	  else if(s[i]==',')
	  {
	     isRight=true;
	  }
	  else if(s[i]==')')
	  {
	     s1.pop();
		 s2.pop();
		 isRight=false;
	  }
	  else
	  {
	  	p=(BiThTree *)malloc(sizeof(BiThTree));
	    p->data=s[i];
        p->lchild=NULL;
        p->rchild=NULL;
        temp=s1.top();
    	if(isRight==true)
        {
          temp->rchild=p;
	      cout<<temp->data<<"的右孩子是"<<s[i]<<endl;
        }
        else if(isRight==false)
        {
          temp->lchild=p;
	      cout<<temp->data<<"的左孩子是"<<s[i]<<endl;
        }		
        if(s[i+1]=='(')
        {  s1.push(p);  }
	  }	  
   i++;
   }
}
void ThInOrder(BiThTree *Thrt)
{
    BiThTree *p = Thrt->lchild;
    while(p != Thrt)
    {
        while(p->LTag == Link) 
		{
			p = p->lchild;
		}
        cout<<p->data;
        while(p->RTag == Thread && p->rchild != Thrt)
        {
            p = p->rchild; 
			cout<<p->data;
        }
        p = p->rchild;
    }
}
int main()
{
    BiThTree *T,*Thrt; 
	T=new BiThTree;
	Thrt=new BiThTree;  
    char s[100];
	cout<<"输入形如A(B,C(D,E))形式的字符串"<<endl;
    cin>>s;
    creatBinTree(s,T);
    cout<<endl;
    Thrt=CreatThread(T);
    ThInOrder(Thrt); 
    return 0;
}

先序线索二叉树

在这里插入图片描述
结构定义:

typedef struct node
{
	int ltag,rtag;//线索标志
	struct node *lchild,rchild;//线索或子女指针
	int data; 
}ThreadNode;

前序遍历二叉树线索化

ThreadNode *pre;		   		//全局变量,始终指向刚访问过的结点 
void  Thread(ThreadNode *&p)    		//对二叉树进行前序序线索化
{    if (p!=NULL)	
     {  
        if(p->lchild==NULL)          	    //左孩子不存在,进行前驱结点线索化
        {     p->lchild=pre; p->ltag=1;  }	//建立当前结点的前驱线索
        else  p->ltag=0;                    //p结点的左子树已线索化
        if(pre!=NULL&&pre->rchild==NULL)	//对pre的后继结点线索化
        {     pre->rchild=p;pre->rtag=1;}	//建立前驱结点的后继线索
        else  pre->rtag=0;
        pre=p;
		Thread(p->lchild);           		//左子树线索化
        Thread(p->rchild);  		        //右子树线索化
     }
} 

建立头结点(同中序遍历)

ThreadNode *PreThread(ThreadNode T)
{
	//前序遍历二叉树T,并将其前序线索化,Th指向头结点。
    ThreadNode *root;
	root = (ThreadNode *)malloc(sizeof(ThreadNode)); //创建头结点
	root->ltag = 0;               //头结点有左孩子,若树非空,则其左孩子为树根
	root->rtag = 1;               //头结点的右孩子指针为右线索
	root->rchild = root;            //头结点的右孩子指针指向根结点 	
	if(!T)
	{
		root->lchild = root;        //若树为空,则左指针也指向自己
	}
	else
	{
		root->lchild = T;          //头结点的左孩子指向根
		pre = root;                //pre初值指向头结点
		PreThread(T);              //调用算法
		pre->rchild = root;        //算法结束后,pre为最右结点,
		pre->rtag = Thread; 
		root->rchild = pre;        //头结点的右线索指向pre
	}
	return root;
}

前序遍历二叉树

void PreInOrder(ThreadNode *Thrt)
{
    ThreadNode *p = Thrt->lchild;
    while(p != Thrt)
    {
        cout<<p->data;
		while(p->ltag == 0) 
		{
			p = p->lchild;
		}       
        while(p->rtag == 1 && p->rchild != Thrt)
        {
            p = p->rchild; 
			cout<<p->data;
        }
        p = p->rchild;
    }
}

后序遍历线索二叉树

在这里插入图片描述
后序遍历线索二叉树时,需要一个parent 指针
后序遍历二叉树线索化

void PostThread(ThreadNode p)
{
	if(p){
		PostThread(p->lchild);     //左子树线索化
		PostThread(p->rchild);     //右子树线索化 
		if(!p->lchild)
		{               //没有左孩子 
			p->ltag = Thread;         //前驱线索 
			p->lchild = pre;          //左孩子指针指向前驱 
		}
		if(pre && !pre->rchild)
		{
			pre->rtag = Thread;       //后继线索
			pre->rchild = p ;         //前驱右孩子指针指向后继 
		}
		pre = p;
	}
}

后序遍历二叉树

void PostOrderTr(ThreadNode T)
{
	ThreadNode p ;
	p = T;            // p指向根节点 
	pre=NULL;
	while(p != NULL){            //空树 或者遍历结束时 p == T
		while(p->ltag == Link )         // 走到最左结点  ||左结点
		{
		    p = p->lchild;
		}			 
		while(p->rtag == Thread )
		{      //访问后继       ||右结点
			cout<<p->data;
			pre = p;
			p = p->rchild ;            
		}
		if(p == T)
		{                     //是否是最后根节点
			cout<<p->data;
			break;
		}
		while(p && p->rchild == pre  )
		{ 
			cout<<p->data;;
			pre = p;
			p = p->parent;
		}
		if(p && p->RTag == Link)
		{
			p = p->rchild;
		}	
	}
}
发布了28 篇原创文章 · 获赞 2 · 访问量 3259

猜你喜欢

转载自blog.csdn.net/Maestro_T/article/details/84206057