您的位置:首页 > 其它

二叉树的递归遍历与非递归算法实现

2013-12-05 11:25 260 查看
通过递归算法与非递归算法的比较,更好地理解各自的特点。非递归其实就是调用栈的基本操作,进栈,出栈等。
这里面也正好复习了下栈的基本算法的实现。

栈和队列的实现在我的前一篇博文里。

基本数据结构
[align=left]typedef struct BiNode[/align]
[align=left]{[/align]
[align=left] char data; //此处,二叉树中节点值类型为字符型[/align]
[align=left] struct BiNode *lchild,*rchild; //左右孩子节点[/align]
[align=left]}BiNode,*BiTree; [/align]
[align=left] [/align]
[align=left]二叉树的创建[/align]
[align=left]先申请根节点的空间,然后赋值,然后分别递归建立其左子树和右子树[/align]

//按照先序序列输入构建一棵二叉树

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "treenode.h"

#include "mystack.h"

#include "myqueue.h"

#include "newstack.h"

//按照先序序列输入构建一棵二叉树

void Create(BiTree &T)

{

char ch;

scanf( "%c",&ch);

if( '#' == ch )

{

T = NULL;

}

else

{

T=(BiNode *)malloc( sizeof(BiNode));

T->data=ch;

Create(T->lchild);

Create(T->rchild);

}

}

//二叉树的先序遍历

void PreOrder(BiTree T)

{

if(T)

{

printf( "%c ",T->data);

PreOrder(T->lchild);

PreOrder(T->rchild);

}

}

//二叉树先序遍历的非递归算法

void PreTraverse(BiTree T)

{

BiNode *p;

Stack S;

S=InitStack();

if(T)

{

Push(S,T);  //根结点指针进栈

while(!StackEmpty(S))

{

p=Pop(S);  //出栈,栈顶元素赋给p

while(p)

{

printf( "%c\t",p->data);  // 访问p结点

if(p->rchild)

Push(S,p->rchild);  //右子树存在时,进栈

p=p->lchild;            //继续沿着左子树往下走

}

}

}

}

//二叉树的中序遍历

void InOrder(BiTree T)

{

if(T)

{

InOrder(T->lchild);

printf( "%c ",T->data);

InOrder(T->rchild);

}

}

//二叉树的中序遍历的非递归算法

void InTraverse(BiTree T)

{

BiNode *p;

Stack S;

S=InitStack();

Push(S,T);  //根结点指针进栈

while(!StackEmpty(S))

{

while((p=GetsTop(S))&&p)  //取栈顶元素且存在,赋给 p

Push(S,p->lchild);    //p的左子树进栈

p=Pop(S);               //去掉最后的空指针

if(!StackEmpty(S))

{

p=Pop(S);       //弹出栈顶元素,赋给p

printf( "%c\t",p->data);   // 访问p结点

Push(S,p->rchild);     //右子树进栈,然后遍历右子树

}

}

}

//二叉树的后序遍历

void PostOrder(BiTree T)

{

if(T)

{

PostOrder(T->lchild);

PostOrder(T->rchild);

printf( "%c ",T->data);

}

}

void PostTraverse(BiTree T)

{

int tag;

BiNode *p;

Stacks S;

SNode sdata;

S=InitStacks();

p=T;

while(p||!StacksEmpty(S))

{

while(p)

{

sdata.q=p;

sdata.tag=0;

Pushs(S,&sdata);   //(p,0)进栈

p=p->lchild;      //遍历p 之左子树

}

sdata=*Pops(S);  //退栈

p=sdata.q;     //取指针

tag=sdata.tag; //状态位

if(tag==0)     //从左子树返回时,根的 tag=0

{

sdata.q=p;

sdata.tag=1;      //这时要进入根的右子树了,所以根的 tag=1,下次碰到根时就可以访问了

Pushs(S,&sdata);   //(p,1)进栈,根还得进一次栈

p=p->rchild;     //遍历右子树

}

else          //tag=1,这是说明了右子树访问完了返回,所以这次要对根进行访问了

{

printf( "%c\t",p->data);

p=NULL;

}

}

}

//二叉树的层次遍历

void LevelTraverse(BiTree T)

{

BiNode *p;

LinkQueue *Q;

InitQueue(Q);

EnQueue(Q,T);

while(!QueueEmpty(Q))

{

p=DeQueue(Q);

printf( "%c\t",p->data);

if(p->lchild!=NULL)

EnQueue(Q,p->lchild);

if(p->rchild!=NULL)

EnQueue(Q,p->rchild);

}

}

int main()

{

BiTree T;

Create(T);

PostOrder(T);

printf( "\n");

LevelTraverse(T);

printf( "\n");

PostTraverse(T);

printf( "\n");

return 0;

}


View Code

[align=left]/*测试数据*/[/align]
[align=left]/* 分别是构建二叉树的输入数据以及先序、中序、后序、层次遍历序列:[/align]
[align=left]ABE##C#D##F#GH#I##J##[/align]
[align=left]ABECDFGHIJ[/align]
[align=left]EBCDAFHIGJ[/align]
[align=left]EDCBIGJGFA[/align]
[align=left]ABFECGDHJI[/align]
[align=left] */[/align]



[align=left]图画得有点丑,见笑了。[/align]

[align=left] [/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: