您的位置:首页 > 其它

二叉树的建立和遍历(递归、非递归)

2015-11-09 21:29 363 查看


从二叉树的遍历的定义可知,3种遍历算法的不同之处在于访问根节点和左右子树的先后关系。如果在算法中暂时忽略访问根节点的printf语句,则3种遍历算法完全相同。因此,从递归执行的角度来看,先序、中序和后序遍历是完全相同的。上图中的用带箭头的虚线表示这3种遍历算法执行的过程。其中,向下的箭头表示更深一层的递归调用,向上的箭头表示从递归调用退出返回;虚线旁的三角形、圆形和方形内的字符分别表示先序、中序和后序遍历二叉树过程中访问节点时输出的信息。

# include<stdio.h>
# include<malloc.h>
# define MAX 100

//二叉树节点
typedef struct BiNode{
char data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree;

//栈
typedef struct{
BiTree data[MAX];
int top;
}Stack;

void createBiTree(BiTree &T);
void PreOrder(BiTree T);
void PreOrder2(BiTree T,Stack &s);
void InOrder(BiTree T);
void InOrder2(BiTree T,Stack &s);
void PostOrder(BiTree T);
void PostOrder2(BiTree T,Stack s1,Stack s2);
int getTop(Stack &s,BiTree &t);
void InitStack(Stack &s);
int isFull(Stack s);
int isEmpty(Stack s);
int Push(Stack &s,BiTree t);
int Pop(Stack &s);

int main()
{
BiTree T=NULL;
Stack s1,s2;
InitStack(s1);
InitStack(s2);
printf("创建二叉树('#'代表空节点):");
createBiTree(T);
printf("\n先序遍历二叉树(递归):");
PreOrder(T);
printf("\n先序遍历二叉树(非递归):");
PreOrder2(T,s1);
printf("\n中序遍历二叉树(递归):");
InOrder(T);
printf("\n中序遍历二叉树(非递归):");
InOrder2(T,s1);
printf("\n后序遍历二叉树(递归):");
PostOrder(T);
printf("\n后序遍历二叉树(非递归):");
PostOrder2(T,s1,s2);
printf("\n");
return 0;
}

//创建二叉树
void createBiTree(BiTree &T)
{
char ch;
scanf("%c",&ch);
if(ch=='#')
{
T=NULL;
return ;
}
else
{
T=(BiTree)malloc(sizeof(BiNode));
T->data=ch;
T->lchild=T->rchild=NULL;
createBiTree(T->lchild);
createBiTree(T->rchild);
}
}

//先序遍历二叉树(递归)
void PreOrder(BiTree T)
{
if(!T)
return ;
else
{
printf("%c ",T->data);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}

//先序遍历二叉树(非递归)
void PreOrder2(BiTree T,Stack &s)
{
if(!T)
return ;
BiTree p=NULL;
InitStack(s);
Push(s,T);
while(!isEmpty(s))
{
//一直向左,直到遇到NULL
while(getTop(s,p)&&p)
{
printf("%c ",p->data);
Push(s,p->lchild);
}
Pop(s);//空指针退栈
if(!isEmpty(s))
{
getTop(s,p);
Pop(s);
Push(s,p->rchild);
}
}
}

//中序遍历二叉树(递归)
void InOrder(BiTree T)
{
if(!T)
return ;
else
{
InOrder(T->lchild);
printf("%c ",T->data);
InOrder(T->rchild);
}
}

//中序遍历二叉树(非递归)
void InOrder2(BiTree T,Stack &s)
{
if(!T)
return ;
BiTree p=NULL;
InitStack(s);
Push(s,T);
while(!isEmpty(s))
{
while(getTop(s,p)&&p) Push(s,p->lchild);//一直向左走到尽头
Pop(s);//空指针出栈
if(!isEmpty(s))
{
getTop(s,p);
printf("%c ",p->data);
Pop(s);
Push(s,p->rchild);
}
}
}
//后序二叉树遍历(递归)
void PostOrder(BiTree T)
{
if(!T)
return ;
else
{
PostOrder(T->lchild);
PostOrder(T->rchild);
printf("%c ",T->data);
}
}

//后序遍历二叉树(非递归)
void PostOrder2(BiTree T,Stack s1,Stack s2)
{
if(!T)
return ;
BiTree p=NULL;
InitStack(s1);
InitStack(s2);
Push(s1,T);
//先按照‘根右左’的顺序遍历,s1作为该遍历顺序的辅助栈。逆过来,就是'左右根'。s1中先访问的节点先压入栈s2.
while(!isEmpty(s1))
{
while(getTop(s1,p)&&p)
{
Push(s2,p);
Push(s1,p->rchild);//一直向右走,直到尽头
}
Pop(s1);//空指针出栈
if(!isEmpty(s1))
{
getTop(s1,p);
Pop(s1);
Push(s1,p->lchild);
}
}
//依次从s2栈顶弹出节点便是按照‘左右根’顺序遍历二叉树
while(!isEmpty(s2))
{
getTop(s2,p);
printf("%c ",p->data);
Pop(s2);
}
}

//初始化栈
void InitStack(Stack &s)
{
s.top=0;
}

//判断栈是否满了,若是,则返回1,否则返回0.
int isFull(Stack s)
{
if(s.top>=MAX)
return 1;
else
return 0;
}

//判断栈是否为空,若是,返回1,否则返回0
int isEmpty(Stack s)
{
if(s.top==0)
return 1;
else
return 0;
}

//入栈,若成功,则返回1,否则返回0
int Push(Stack &s,BiTree t)
{
if(isFull(s))
return 0;
else
{
s.data[s.top]=t;
s.top++;
return 1;
}
}

//出栈,若出栈成功,则返回1,否则返回0
int Pop(Stack &s)
{
if(isEmpty(s))
return 0;
else
{
s.top--;
return 1;
}
}

//获得栈顶元素,成功返回1,失败返回0
int getTop(Stack &s,BiTree &t)
{
if(isEmpty(s))
return 0;
else
{
t=s.data[s.top-1];
return 1;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: