// 二叉树的三种遍历方法(终结版)
#include<stdio.h>
#include<stdlib.h>
typedef struct Bitree
{
int data;
struct Bitree *lchild,*rchild;
}BitreeNode,*LinkBitree;
typedef struct Stack
{
LinkBitree data[40];
int top,bottom;
}Stack,*StackList;
LinkBitree CreatBitree();
StackList InitStack();
void preordertraverse(LinkBitree);
void Inordertraverse(LinkBitree);
void Postordertraverse(LinkBitree) ;
//int preordertraverse(LinkBitree);
//int Inordertraverse(LinkBitree);
//int Postordertraverse(LinkBitree) ;
int visit(int);
int main()
{
LinkBitree BitreeHead;
printf("请输入根结点的值:e= ");
BitreeHead=CreatBitree();
//StackList Stack;
//Stack=InitStack(); //换做在遍历的时候初始化
preordertraverse(BitreeHead);
Inordertraverse(BitreeHead);
Postordertraverse(BitreeHead);
return 0;
}
LinkBitree CreatBitree()
{
int edata;
LinkBitree Head;
scanf("%d",&edata);
if(edata==0)
{
Head=NULL;
}
else
{
Head=(LinkBitree)malloc(sizeof(BitreeNode));
if(Head==NULL)
{
printf("内存分配失败!!");
exit(0);
}
else
{
Head->data=edata;
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 preordertraverse(LinkBitree Head)
{
StackList Stack;
Stack=InitStack(); // 初始化栈
printf("先序遍历结果\n");
do
{
while(Head)//先序遍历,一直到最左下的位置
{
visit(Head->data);
Stack->data[Stack->top]=Head;//入栈
Stack->top=Stack->top+1;
Head=Head->lchild;
}
if(Stack->top)//栈不为空
{
Stack->top--;
Head=Stack->data[Stack->top]; //出栈
Head=Head->rchild;
}
}while(Stack->top||Head);
printf("\n\n");
}
/* //递归访问程序
int preordertraverse(LinkBitree T)
{
printf("先序遍历结果\n");
if(T)
{
if(visit (T->data))
if(preordertraverse(T->lchild))
if(preordertraverse(T->rchild)) return 1;
return 0; // 实际上,无论访问哪个结点,都不会输出0,对于空指针,直接返回1 对于 非空指针,递归访问其左子树右子树
}
else
return 1; //访问到根节点的左右子树,返回1
printf("\n\n");
}*/
void Inordertraverse(LinkBitree Head) //非递归中续遍历
{
StackList Stack;
Stack=InitStack(); // 初始化栈
printf("遍历结果\n");
do
{
while(Head)//先序遍历,一直到最左下的位置
{
Stack->data[Stack->top]=Head;//入栈
Stack->top=Stack->top+1;
Head=Head->lchild;
}
if(Stack->top)//栈不为空
{
Stack->top--;
Head=Stack->data[Stack->top]; //出栈
visit(Head->data);
Head=Head->rchild;
}
}while(Stack->top||Head);
printf("\n\n");
}
//递归访问程序 中序遍历
/*int Inordertraverse(LinkBitree T)
{
if(T)
{
if(Inordertraverse(T->lchild))
if(visit (T->data))
if(Inordertraverse(T->rchild)) return 1;
return 0; // 实际上,无论访问哪个结点,都不会输出0,对于空指针,直接返回1 对于 非空指针,递归访问其左子树右子树
}
else
return 1; //访问到根节点的左右子树,返回1
}*/
/*
实现二叉树的后序遍历二叉树后序遍历的思想:
从根节点开始,沿左子树一直走到没有左孩子的节点为止,并将所经[节点]的地址第一次进栈;当找到没有左孩子的节点时,此节点的左子树已访问完毕;
从栈顶退出该节点,判断该节点是否为第一次进栈,如是,再将所经[节点]的地址第二次进栈,并沿该节点的右子树一直走到没有右孩子的节点为止,如否,则访问该节点;此时,该节点的
左、右子树都已完全遍历,且令指针p = NULL;
如此重复到栈空为止。
*/
void Postordertraverse(LinkBitree Head_m) //非递归后续遍历
{
StackList Stack;
int Tag[40]; //栈,用于标识结点的进栈次数
LinkBitree Head = Head_m;
Stack=InitStack(); // 初始化栈
printf("后序遍历结果\n");
do
{
while(Head)//先序遍历,一直到最左下的位置
{
Stack->data[Stack->top]=Head;//入栈
Tag[Stack->top] = 0; // 注意栈中i个元素与Tag中第i+1个元素对应
Stack->top=Stack->top+1;
Head=Head->lchild;
}
Stack->top = Stack->top -1 ;
Head=Stack->data[Stack->top]; //出栈
if(0 == Tag[Stack->top])//如果该结点是第1次进栈
{
Stack->data[Stack->top]=Head;//再次入栈
Tag[Stack->top] = 1;
Stack->top=Stack->top+1;
Head=Head->rchild; // 搜索该结点的右子树
}
else
{
//Stack->top--;
//Head=Stack->data[Stack->top]; //if之前已经出栈过了
visit(Head->data);
Tag[Stack->top] = 0;
Head = NULL; //这是程序退出的条件之一,也不会再次经过while(Head)
}
}while(Stack->top||Head);
printf("\n\n");
}
/*
//递归访问程序 后序遍历
int Postordertraverse(LinkBitree T)
{
if(T)
{
if(Postordertraverse(T->lchild));
if(Postordertraverse(T->rchild));
if (visit (T->data))
return 1;
return 0; // 实际上,无论访问哪个结点,都不会输出0,对于空指针,直接返回1 对于 非空指针,递归访问其左子树右子树
}
else
return 1; //访问到根节点的左右子树,返回1
}
*/