回 帖 发 新 帖 刷新版面

主题:[讨论][老话题]二叉树的遍历

二叉树的遍历有3种方式:

         a
        / \
       /   \
      b     e
     / \     \
    /   \     \
   c     d     f

(先序)先根遍历:(根左右)先访问根,再访问左子树,最后访问右子树,则可得如下的序列:abcdef

(中序)中根遍历:(左根右)先访问左子树,再访问根,最后访问右子树,则可得如下的序列:cbdaef

(后序)后根遍历:(左右根)先访问左子树,再访问右子树,最后访问根,则可得如下的序列:cdbfea




本文给出二叉树先序、中序、后序三种遍历的非递归算法,此三个算法可视为标准算法。

1.先序遍历非递归算法
#define maxsize 100
typedef struct
{
Bitree Elem[maxsize];
int top;
}SqStack;

void PreOrderUnrec(Bitree t)
{
SqStack s;
StackInit(s);
p=t;

while (p!=null || !StackEmpty(s))
{
while (p!=null) //遍历左子树
{
visite(p->data);
push(s,p);
p=p->lchild;
}//endwhile

if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历
{
p=pop(s);
p=p->rchild;
}//endif

}//endwhile

}//PreOrderUnrec

2.中序遍历非递归算法
#define maxsize 100
typedef struct
{
Bitree Elem[maxsize];
int top;
}SqStack;

void InOrderUnrec(Bitree t)
{
SqStack s;
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //遍历左子树
{
push(s,p);
p=p->lchild;
}//endwhile

if (!StackEmpty(s))
{
p=pop(s);
visite(p->data); //访问根结点
p=p->rchild; //通过下一次循环实现右子树遍历
}//endif

}//endwhile

}//InOrderUnrec


3.后序遍历非递归算法
#define maxsize 100
typedef enum{L,R} tagtype;
typedef struct
{
Bitree ptr;
tagtype tag;
}stacknode;

typedef struct
{
stacknode Elem[maxsize];
int top;
}SqStack;

void PostOrderUnrec(Bitree t)
{
SqStack s;
stacknode x;
StackInit(s);
p=t;

do
{
while (p!=null) //遍历左子树
{
x.ptr = p;
x.tag = L; //标记为左子树
push(s,x);
p=p->lchild;
}

while (!StackEmpty(s) && s.Elem[s.top].tag==R)
{
x = pop(s);
p = x.ptr;
visite(p->data); //tag为R,表示右子树访问完毕,故访问根结点
}

if (!StackEmpty(s))
{
s.Elem[s.top].tag =R; //遍历右子树
p=s.Elem[s.top].ptr->rchild;
}
}while (!StackEmpty(s));
}//PostOrderUnrec

回复列表 (共7个回复)

沙发

个人感觉递归无论从二叉树本身的结构还是理解上都要更胜一筹,当然也不是说你这个不好。

板凳

不用递归程序蛮难懂的.

3 楼

#define maxsize 100
typedef struct
{
Bitree Elem[maxsize];
int top;
}SqStack;
这里面"Bitree"是什么我没见过

4 楼

2叉树的节点(node)。

5 楼

非递归算法效率应该比递归高吧?

6 楼

差不多吧。反正都是堆栈。

7 楼


是啊,递归算法简明精炼,但效率较低,在实际应用中往往会用到非递归算法,
但是本人觉得,适合你就是好的

我来回复

您尚未登录,请登录后再回复。点此登录或注册