您的位置:首页 > 理论基础 > 数据结构算法

二叉树的前序中序线索化及对对应线索二叉树的遍历

2013-08-27 22:01 423 查看
《数据结构》

最近在看数据结构,这里给下我自己弄的程序(当然是参考书上的了)

对二叉树的线索化分前序和中序两种,分别给出了递归与非递归的方法。

对于后序线索二叉树的遍历还有些问题。(其实是后序线索二叉树太鸡肋了,我感觉没啥用)

// 二叉树的线索化与遍历

#include<stdio.h>
#include<stdlib.h>

typedef struct BiThrNode
{
int data;
struct BiThrNode *Lchild,*Rchild;
int Ltag, Rtag; //线索标志0,表示孩子结点 1表示前驱或后继结点
}BiThrNode,*BiThrBitree;

typedef struct Stack
{
BiThrBitree data[40];
int top,bottom;
}Stack,*StackList;

BiThrBitree CreatBitree();
StackList InitStack();

void PreThreading(BiThrBitree);
//void InThreading(BiThrBitree);
//void PostThreading(BiThrBitree);
BiThrBitree OrderThreading(BiThrBitree);
void PreorderTraverse_Thr(BiThrBitree);
//void InorderTraverse_Thr(BiThrBitree);
//void PostorderTraverse_Thr(BiThrBitree);

BiThrBitree pre;

int main()
{
BiThrBitree BitreeHead, T;
printf("请输入根结点的值:e=  ");
BitreeHead = CreatBitree();
T = OrderThreading(BitreeHead);
//PreorderTraverse_Thr(T);
//InorderTraverse_Thr(T);
PostorderTraverse_Thr(T);
return 0;
}

BiThrBitree CreatBitree()
{
int edata;
BiThrBitree Head;
scanf("%d",&edata);
if(edata==0)
{
Head=NULL;
}
else
{
Head=(BiThrBitree)malloc(sizeof(BiThrNode));
if(Head==NULL)
{
printf("内存分配失败!!");
exit(0);
}
else
{
Head->data=edata;
Head->Ltag = Head->Rtag = 0; //初始化为0
printf("请输入结点%d的左孩子的值:e= ",Head->data);
Head->Lchild=CreatBitree();
printf("请输入结点%d的右孩子的值:e= ",Head->data);
Head->Rchild=CreatBitree();
}
}
return Head;
}

StackList InitStack()
{
StackList Stack;
Stack=(StackList)malloc(sizeof(Stack));
if(Stack==NULL)
{
printf("内存分配失败!!");
exit(0);
}
else
{
Stack->top=0;
Stack->bottom=0;
}
return Stack;
}

int visit(int a)
{
printf("%5d",a);

return 1;
}

void PreThreading(BiThrBitree Head)//先序遍历的递归算法 将二叉树线索化
{
if(Head)
{
if(!Head->Lchild){Head->Ltag=1; Head->Lchild = pre;}//处理该结点
if(!pre->Rchild){pre->Rtag = 1; pre->Rchild = Head;}
pre=Head;

//因为先序是先处理根结点,如果前面已补充了根节点的前驱,使得Head->Lchild不为空,会造成死循环
if(!Head->Ltag)
PreThreading(Head->Lchild); //处理左子树
if(!Head->Rtag)
PreThreading(Head->Rchild); //处理右子树

}
return;
}

/*
void PreThreading(BiThrBitree Head)//先序遍历的非递归算法 将二叉树线索化
{
StackList Stack;
Stack=InitStack();

do
{
while(Head)
{
if(!Head->Lchild){Head->Ltag=1; Head->Lchild = pre;}//处理该结点
if(!pre->Rchild){pre->Rtag = 1; pre->Rchild = Head;}
pre=Head;
Stack->data[Stack->top++] = Head; //入栈
if(0==Head->Ltag)//先序遍历是先处理结点,在遍历左子树前要判断左孩子是前驱还是左子树
Head = Head->Lchild;
else break;

}
if(Stack->top)
{
Stack->top--;
Head=Stack->data[Stack->top]; //出栈
Head = Head->Rchild;
}

}while(Stack->top||Head);

}
*/

/*
void InThreading(BiThrBitree Head)//中序遍历的递归算法 将二叉树线索化
{

if(Head){
InThreading(Head->Lchild); //处理左子树
if(!Head->Lchild){Head->Ltag=1; Head->Lchild = pre;}//处理该结点
if(!pre->Rchild){pre->Rtag=1; pre->Rchild = Head;}
pre=Head;
InThreading(Head->Rchild); //处理右子树

}
return;
}
*/
/*
void InThreading(BiThrBitree Head) //中序遍历的非递归算法,将二叉树线索化
{
StackList Stack;
Stack=InitStack();
do
{
while(Head)
{
Stack->data[Stack->top++] = Head; //入栈
Head = Head->Lchild;
}
if(Stack->top)
{
Head = Stack->data[--Stack->top];	  //出栈
if(!Head->Lchild)	{Head->Ltag=1; Head->Lchild = pre;}//处理该结点
if(!pre->Rchild)	{pre->Rtag=1; pre->Rchild = Head;}
pre = Head;
Head = Head->Rchild;
}

}while((Stack->top||Head));

}
*/

BiThrBitree OrderThreading(BiThrBitree Head)//二叉树的XX序遍历线索化
{
//二叉树的线索表上添加了一个头结点Thrt,其Lchild域指针指向二叉树根节点,Rchild域指针指向中序遍历时访问的最后一个结点
BiThrBitree Thrt;
if(!(Thrt = (BiThrBitree)malloc(sizeof(BiThrNode)))) exit(1);
Thrt->data = 0;
Thrt->Ltag = 0; Thrt->Rtag = 1;//为了在第一判断的时候不改变根节点的右孩子值
Thrt->Rchild = Thrt;

if(!Head){Thrt->Lchild = Thrt;}
else
{
Thrt->Lchild = Head; pre = Thrt;
//PreThreading(Head);
//InThreading(Head);
PostThreading(Head);
pre->Rchild = Thrt; pre->Rtag = 1; //最后一个结点的线索化
Thrt->Rchild = pre;

}

return Thrt;

}

//线索二叉树注意问题:
//对于根节点,其左右子树再也不是NULL了,所以不能以head=NULL作为判断依据,如果按照以前的判断条件,一直遍历左子树将会得到死循环
void PreorderTraverse_Thr(BiThrBitree T)
{ // 对线索二叉树的先序遍历

BiThrBitree Head;
Head = T->Lchild;
printf("先序遍历结果\n");
while(Head!=T)
{

while(0==Head->Ltag&&Head)//先序遍历到左下角(head = 左下角的结点,此结点还未被访问)//0==Head->Ltag表示head存在左结点
{
visit(Head->data);
Head = Head->Lchild;
}

visit(Head->data);
Head = Head->Rchild; //这儿无论后继还是右孩子都一样

}
printf("\n\n");
}

/*
void InorderTraverse_Thr(BiThrBitree T){ // 对线索二叉树的中序遍历

BiThrBitree Head;
Head = T->Lchild;
printf("中序遍历结果\n");
while(Head!=T)
{

while(0==Head->Ltag) //先找到最左下的结点
{
Head = Head->Lchild;
}
visit(Head->data);
while(1==Head->Rtag&&Head->Rchild!=T) //如果Head的右子树为空,跳到其后继
{
Head = Head->Rchild;
visit(Head->data);
}
Head = Head->Rchild; // 调到后继的右子树或者是head的右子树

}
printf("\n\n");
}
*/


如果大家感兴趣,我也做了下后序遍历的线索化,但是在编写后序线索二叉树的遍历程序时,蛋疼的发现后序遍历的线索二叉树真心废物一枚。

// 后序遍历线索化
/*
void PostThreading(BiThrBitree Head)//后遍历的递归算法 将二叉树线索化
{

if(Head){
PostThreading(Head->Lchild); //处理左子树

PostThreading(Head->Rchild); //处理右子树

if(!Head->Lchild){Head->Ltag=1; Head->Lchild = pre;}//处理该结点
if(!pre->Rchild){pre->Rtag = 1; pre->Rchild = Head;}
pre=Head;

}
return;
}*/

/*
void PostThreading(BiThrBitree Head)//中序遍历的递归算法 将二叉树线索化
{
StackList Stack;
int Tag[40];
Stack = InitStack();

do
{
while(Head)
{
Stack->data[Stack->top] = Head; //入栈
Tag[Stack->top] = 0;
Stack->top++;
Head = H
4000
ead->Lchild;
}

Head = Stack->data[--Stack->top]; //出栈

if(0==Tag[Stack->top])
{
Stack->data[Stack->top] = Head; //再次入栈
Tag[Stack->top] = 1;
Stack->top++;
Head = Head->Rchild;
}
else
{
if(!Head->Lchild){Head->Ltag=1; Head->Lchild = pre;}//处理该结点
if(!pre->Rchild){pre->Rtag = 1; pre->Rchild = Head;}
pre=Head;
Head = NULL; //继续出栈
}

}while(Stack->top||Head)

}
*/
有问题请留言,欢迎讨论~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息