《数据结构》
最近在看数据结构,这里给下我自己弄的程序(当然是参考书上的了)
对二叉树的线索化分前序和中序两种,分别给出了递归与非递归的方法。
对于后序线索二叉树的遍历还有些问题。(其实是后序线索二叉树太鸡肋了,我感觉没啥用)
// 二叉树的线索化与遍历
#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 = Head->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)
}
*/
有问题请留言,欢迎讨论~~