中序线索二叉树
实现代码如下
#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;
}
}
}