初学数据结构(中序线索化二叉树)
初学数据结构(中序线索化二叉树)
《数据结构教程》P243 exp7-4
交作业版
//
// Created by Snow on 2023/4/5.
//
#include<cstdio>
#include<cstdlib>
#define MaxSize 50
typedef char ElemType;
typedef struct node
{
ElemType data;
int ltag,rtag;
struct node *lchild;
struct node *rchild;
}TBTNode;
void CreateTBTree(TBTNode *&b,const char *str)
{
TBTNode *St[MaxSize],*p=nullptr;
int top=-1,k,j=0;
char ch;
b=nullptr;
ch=str[j];
while(ch!='\0')
{
switch(ch)
{
case '(':top++;St[top]=p;k=1;break;
case ')':top--;break;
case ',':k=2;break;
default:
p=(TBTNode*)malloc(sizeof(TBTNode));
p->data=ch;
p->lchild=p->rchild=nullptr;
if(b==nullptr)
b=p;
else
{
switch(k)
{
case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
}
}
}
j++;
ch=str[j];
}
}
void DispTBTree(TBTNode *b)
{
if(b!=nullptr)
{
printf("%c",b->data);
if(b->lchild!=nullptr||b->rchild!=nullptr)
{
printf("(");
DispTBTree(b->lchild);
if(b->rchild!=nullptr)printf(",");
DispTBTree(b->rchild);
printf(")");
}
}
}
TBTNode *pre;
void Thread(TBTNode *&p)
{
if(p!=nullptr)
{
Thread(p->lchild);
if(p->lchild==nullptr)
{
p->lchild=pre;
p->ltag=1;
}
else
{
p->ltag=0;
}
if(pre->rchild==nullptr)
{
pre->rchild=p;
pre->rtag=1;
}
else
{
pre->rtag=0;
}
pre=p;
Thread(p->rchild);
}
}
TBTNode *CreateThread(TBTNode *b)
{
TBTNode *root;
root=(TBTNode*)malloc(sizeof(TBTNode));
root->ltag=0;
root->rtag=1;
root->rchild=b;
if(b==nullptr)
root->lchild=root;
else
{
root->lchild=b;
pre=root;
Thread(b);
pre->rchild=root;
pre->rtag=1;
root->rchild=pre;
}
return root;
}
void ThInOrder(TBTNode *tb)
{
TBTNode *p=tb->lchild;
while(p!=tb)
{
while(p->ltag==0)
p=p->lchild;
printf("%c",p->data);
while(p->rtag==1&&p->rchild!=tb)
{
p=p->rchild;
printf("%c",p->data);
}
p=p->rchild;
}
}
void DestroyTBTree1(TBTNode *&b)
{
if(b->ltag==0)
DestroyTBTree1(b->lchild);
if(b->rtag==0)
DestroyTBTree1(b->rchild);
free(b);
}
void DestroyTBTree(TBTNode *&tb)
{
DestroyTBTree1(tb->lchild);
free(tb);
}
void Disp(TBTNode *b)
{
if(b==nullptr)
return;
if(b->ltag==0)
Disp(b->lchild);
printf("%c",b->data);
if(b->rtag==0)
Disp(b->rchild);
}
int main()
{
TBTNode *b,*tb;
CreateTBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
DispTBTree(b);
printf("\n构造中序线索化二叉树\n");
tb=CreateThread(b);
printf("非递归输出:");
ThInOrder(tb);
printf("\n");
printf("递归输出:");
Disp(tb->lchild);
printf("\n销毁线索二叉树\n");
DestroyTBTree(tb);
return 1;
}
注释版
//
// Created by Snow on 2023/4/3.
//
#include<cstdio>
#include<cstdlib>
#define MaxSize 50
typedef char ElemType;
typedef struct node
{
ElemType data;
int ltag,rtag;//增加的线索标记,值为0表示lchild(rchild)指向左(右)孩子结点,为1表示指向前驱(后继)结点
struct node *lchild;
struct node *rchild;
}TBTNode;
void CreateTBTree(TBTNode *&b,const char *str)
{
TBTNode *St[MaxSize],*p=nullptr;
int top=-1,k,j=0;
char ch;
b=nullptr; //建立的二叉树初始时为空
ch=str[j];
while (ch!='\0') //str未扫描完时循环
{
switch(ch)
{
case '(':top++;St[top]=p;k=1;break; //为左节点
case ')':top--;break;
case ',':k=2; break; //为右节点
default:
p=(TBTNode *)malloc(sizeof(TBTNode));
p->data=ch;
p->lchild=p->rchild=nullptr;
if (b==nullptr) //*p为二叉树的根节点
b=p;
else //已建立二叉树根节点
{
switch(k)
{
case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
}
}
}
j++;
ch=str[j];
}
}
void DispTBTree(TBTNode *b)
{
if (b!=nullptr)
{
printf("%c",b->data);
if (b->lchild!=nullptr || b->rchild!=nullptr)
{
printf("(");
DispTBTree(b->lchild);
if (b->rchild!=nullptr) printf(",");
DispTBTree(b->rchild);
printf(")");
}
}
}
//中序线索二叉树
TBTNode *pre;//全局变量
void Thread(TBTNode *&p)//对二叉树p进行中序线索化
{
if(p!=nullptr)
{
Thread(p->lchild);//左子树线索化
if(p->lchild==nullptr)//左孩子不存在,进行前驱结点线索化
{
p->lchild=pre;//建立当前结点的前驱结点线索
p->ltag=1;
}
else//p结点的左子树已线索化
{
p->ltag=0;
}
if(pre->rchild==nullptr)//对pre的后继结点线索化
{
pre->rchild=p;//建立前驱结点的后继结点线索
pre->rtag=1;
}
else
{
pre->rtag=0;
}
pre=p;
Thread(p->rchild);//右子树线索化
}
}
TBTNode *CreateThread(TBTNode *b)//中序线索化二叉树
{
TBTNode *root;
root=(TBTNode*)malloc(sizeof(TBTNode));//创建头结点
root->ltag=0;
root->rtag=1;
root->rchild=b;
if(b==nullptr)//空二叉树
root->lchild=root;
else
{
root->lchild=b;
pre=root;//pre是结点p的前驱结点,供加线索用
Thread(b);//中序遍历线索化二叉树
pre->rchild=root;//最后处理,加入指向头结点的线索
pre->rtag=1;
root->rchild=pre;//头结点右线索化
}
return root;
}
void ThInOrder(TBTNode *tb)//tb指向中序线索二叉树的头结点
{
TBTNode *p=tb->lchild;//p指向根节点
while(p!=tb)
{
while(p->ltag==0)//找开始结点
p=p->lchild;//访问开始结点
printf("%c ",p->data);
while(p->rtag==1&&p->rchild!=tb)
{
p=p->rchild;
printf("%c ",p->data);
}
p=p->rchild;
}
}
//递归遍历中序线索树
void InOrder(TBTNode *b)
{
if(b==nullptr) //如果当前结点为空,直接返回
return;
if(b->ltag==0)//如果当前结点的左标志域为0,表示有左孩子,递归调用函数处理左孩子
InOrder(b->lchild);
printf("%c",b->data);//输出当前结点的值
if(b->rtag==0)//如果当前结点的右标志域为0,表示有右孩子,递归调用函数处理右孩子
InOrder(b->rchild);
}
void DestroyTBTree1(TBTNode *&b) //销毁
{ if (b->ltag==0) //节点b有左孩子,释放左子树
DestroyTBTree1(b->lchild);
if (b->rtag==0) //节点b有右孩子,释放右子树
DestroyTBTree1(b->rchild);
free(b);
}
void DestroyTBTree(TBTNode *&tb) //销毁一棵带头结点的中序线索树tb
{
DestroyTBTree1(tb->lchild); //释放以tb->lchild为根节点的树
free(tb); //释放头节点
}
int main()
{
TBTNode *b,*tb;
CreateTBTree(b,"A(B(D(,G)),C(E,F))");
DispTBTree(b);printf("\n");
tb=CreateThread(b);
ThInOrder(tb);printf("\n");
DestroyTBTree(tb);
return 1;
}