二叉树的非递归遍历

Posted wkfvawl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的非递归遍历相关的知识,希望对你有一定的参考价值。

二叉树的递归遍历很好写,也很好理解。但因为是递归程序,不可避免地需要调用系统栈,耗时较长,这里我们来探究一下二叉树的非递归遍历的算法。这种方法需要使用栈这种数据结构,这里关于栈的一些操作函数可以看成伪代码吧,先给出线序、中序、后序遍历的代码即说明。

 

先序遍历:

 1 void PreOrderTraverse(BinTree b)
 2 {
 3     InitStack(S);///初始化创建栈
 4     BinTree p=b;///p为工作指针
 5     while(p||!isEmpty(s))
 6     {
 7         while(p)///到最左下的孩子
 8         {
 9             printf(" %c ",p->date);///先序先遍历结点
10             Push(S,p);///入栈
11             p=p->lchild;
12         }
13         if(!isEmpty(s))///在栈不为空的情况下,左孩子为空,弹出该结点,遍历右孩子
14         {
15             p=Pop(s);
16             p=p->rchild;
17         }
18     }
19 }

 

中序遍历:

 1 void InOrderTraverse(BinTree b)
 2 {
 3     InitStack(S);///初始化创建栈
 4     BinTree p=b;///p为工作指针
 5     while(p||!isEmpty(s))
 6     {
 7         while(p)
 8         {
 9             Push(S,p);///中序现将结点进栈保存
10             p=p->lchild;
11         }///遍历到左下角尽头再出栈访问
12         p=Pop(s);
13         printf(" %c ",p->data);
14         p=p->rchild;///遍历右孩子
15     }
16 }


后序遍历:后序遍历较前两种遍历方法比较难实现,原因在于需要遍历完左子树,遍历完右子树,最后才去访问根节点。这样栈顶结点可能会从他的左子树返回,也有可能从他的右子树返回,需要区分这种情况,如果是第一次从左子树返回,那么还需要去遍历其右子树,如果是从右子树返回,那么直接返回该结点就可以了。这里使用辅助指针来区分来源。

void PostOrderTraverse(BinTree b)
{
    InitStack(S);///初始化创建栈
    BinTree p=b, r=NULL;///p为工作指针,辅助指针r
    while(p||!isEmpty(s))
    {
        if(p)///从根节点到最左下角的左子树都入栈
        {
            Push(S,p);///中序现将结点进栈保存
            p=p->lchild;
        }
        else
        {
            GetTop(S,p);///取栈顶,注意!不是出渣!
            if(p->rchild&&p->rchild!=r)///1.右子树还没有访问并且右子树不空,第一次栈顶
            {
                p=p->rchild;///进入右子树
            }
            else///右子树已经访问或为空,接下来出栈访问结点,第二次栈顶
            {
                p=Pop(s);
                printf(" %c ",p->data);
                r=p;///指向访问过的右子树结点
                p=NULL;///使p为空继续访问栈顶
            }
        }
    }
}

 

层次遍历:

从二叉树的第一层(根节点)开始,从上至下逐层遍历,在每一层中又按照从左到右的顺序对结点逐个遍历。我们可以看出如果某个结点比同一层的先遍历,其孩子也将比其同层的孩子结点先遍历,这种先进先出的方式,不就是队列这种数据结构吗?

 1 void LevelOrder(BiTree b)
 2 {
 3     InitQueue(Q);///初始化建立队列
 4     BinTree p;
 5     EnQueue(Q,b);///根节点入队
 6     while(!isEmpty(Q))///队列不空循环
 7     {
 8         DeQueue(Q,p);///队头元素出队
 9         prinf(" %c ",p->data);
10         ///左右孩子入队
11         if(p->lchild!=NULL)
12         {
13             EnQueue(Q,p->lchild);
14         }
15         if(p->rchild!=NULL)
16         {
17             EnQueue(Q,p->rchild);
18         }
19     }
20 }

 

以上是关于二叉树的非递归遍历的主要内容,如果未能解决你的问题,请参考以下文章

最简方式实现二叉树的非递归遍历

二叉树的非递归遍历

转更简单的非递归遍历二叉树的方法

《数据结构》遍历二叉树的非递归算法的疑问。

二叉树经典题之二叉树的非递归遍历

[算法]二叉树的非递归遍历算法