非递归的后序遍历

24 篇文章 0 订阅
24 篇文章 0 订阅
非递归、仅用一个栈、不加标记数组实现二叉树的后序遍历算法
原文出处:
http://www.cnblogs.com/finallyliuyu/archive/2011/08/20/2146989.html

作者:finallyly 出处:博客园(转载请注明作者和出处)

题记:最近在复习数据结构和算法。由于之前在数据结构和算法方面没有受过密集的训练。所以刚入门,有点吃力。最主要的一个问题是:看别人的,好像一看就全懂了,但是自己写又写不出来;给定一个具体的题目,即便是看懂了别人的算法,但是过些日子回过头来自己写,还是写不出来。和我一样出现上述状况的同学要注意啦,需要改变学习方式,否则则会一直在津津有味,乐此不疲,且自以为是地做着无用功。时间是有限的,何必浪费掉大好的时间和青春去做些无意义的事情呢?静下心来想一想,任何一本《数据结构与算法》的教材无非是想告诉我们有一些编程中可以使用的工具(栈、队列、链表、二叉树、图)以及针对如何使用这些工具应用举例而已。因此,我们只要领会到精神,就算学明白了数据结构,可是如何用数据结构实现算法呢?这体现的是自己的逻辑,永远没有什么范式,也不要去过度迷信别人。只要思路对头,你也可以设计出有效果的算法来。

      对于设计算法,个人总结可以分两步:第一步:用自然语言体现出自己的思路,第二步,计算机程序亲和型的伪代码;第三步:把自己的思路用程序实现。第一步到第二步的过渡是要求,你的思路是和程序逻辑相亲和的,即用程序可以实现的。下面切入正题,讲诉非递归、仅用一个栈、不加标记数组实现二叉树的后序遍历算法的思路。

二叉树图例如上图。

第一步:思路

思路,根据二次树的结构特点,产生了如下的思路

1. 根节点入栈

2. 如果栈非空,则获取栈顶元素

3. 如果左孩子存在,则入栈左孩子

4. 如果左孩子不存在,但是右孩子存在则入栈右孩子

5. 如果左、右孩子都不存在,那么栈顶元素出栈,并访问已经出栈的栈顶元素

5.1 如果已出栈的元素是当前栈顶元素的左孩子,那么入栈右孩子

5.2如果已出栈元素是当前栈顶元素的右孩子,那么继续出栈并且访问当前栈顶元素

第二步,计算机程序亲和伪代码

思路如何变成计算机可以执行的逻辑?

考虑我们注意到 (1)5.1-5.2之间存在循环逻辑;(2)5.1 与3之间有逻辑重复。对于(1)我们可以写一个while循环,对于(2)我们可以设置一个开关变量flag,用来控制当前栈顶结点的左孩子是否参与入栈活动。

C++风格的伪代码如下

Bool PostOrderTraverse(Bitree T)

{

InitStack(S);

Push(S,T);

flag=0;

While(!Empty(S))

{

Bitree e;

GetTop(S,e);

if (e->lchild&&!flag)

{

Push(S,e->lchild);

}

else

{

if(e->rchild)

{

Push(S,e->rchild);

flag=0;

}

Else

{

Bitree pOldTop;

GetTop(S,pOldTop);

Pop(S);

Visit(pOldTop);

While(!Empty(S))

{

BiTree pNewTop;

GetTop(S,pNewTop);

if (pOldTop=pNewTop->lchild)

{

flag=1;

break;

}

else

{

Pop(S);

Visit(pNewTop);

}
}
}
}
}
第三步:代码实现

复制代码
bool PostOrderTraverseByStack(BiTree T)
{
        stack
< BiTree > bitreeStack;
    bitreeStack.push(T);
int flag = 0 ;

while ( ! bitreeStack.empty())
    {
        BiTree pTree
= bitreeStack.top();
if (pTree -> lchild &&! flag)
        {
            bitreeStack.push(pTree
-> lchild);
        }
else // 无需插入左孩子的模式
{
if (pTree -> rchild)
            {
                bitreeStack.push(pTree
-> rchild);
                flag
= 0 ;
            }
else
            {

                BiTree pTopOld
= bitreeStack.top();
                bitreeStack.pop();
                cout
<< pTopOld -> data << endl;
while ( ! bitreeStack.empty())
                {

if ( ! bitreeStack.empty())
                    {
                        BiTree pTopNew
= bitreeStack.top();
if (pTopOld == pTopNew -> lchild)
                        {
                            flag
= 1 ;
break ;

                        }
else
                        {
                            cout
<< pTopNew -> data << endl;
                            bitreeStack.pop();
                            pTopOld
= pTopNew;
                            flag
= 0 ;


                        }


                    }
else
                    {
break ;
                    }

                }


            }
        }


    }
return true ;

}
复制代码

为了便于大家验证,把二叉树建树、销树、主函数验证的代码张贴如下

复制代码
#include < iostream >
#include
< deque >
#include
< stack >
using namespace std;
typedef
struct BiTNode
{
char data;
    BiTNode
* lchild;
    BiTNode
* rchild;
}BiTNode,
* BiTree;

bool CreateBiTree(BiTree & T,deque < char >& charQue)
{

if ( ! charQue.empty())
    {
char ch = charQue.front();
        charQue.pop_front();
if (ch == ' ' )
        {
            T
= NULL;
        }
else
        {
            T
= new BiTNode;
            T
-> data = ch;
            CreateBiTree(T
-> lchild,charQue);
            CreateBiTree(T
-> rchild,charQue);

        }
return true ;
    }
return true ;

}
bool PostOrderTraverse(BiTree T)
{
if (T)
    {
if (PostOrderTraverse(T -> lchild))
        {
if (PostOrderTraverse(T -> rchild))
            {
                cout
<< T -> data << endl;
return true ;
            }
        }
return false ;
    }
else
    {
return true ;
    }
}
bool DestroyTree(BiTree & T)
{
if (T != NULL)
    {
if (DestroyTree(T -> lchild))
        {
if (DestroyTree(T -> rchild))
            {
                delete T;
return true ;
            }


        }
return false ;


    }
else
    {
return true ;
    }


}
int main()
{
   BiTree root;
   deque
< char > charQue;
   charQue.push_back(
' A ' );
   charQue.push_back(
' B ' );
   charQue.push_back(
' C ' );
   charQue.push_back(
' ' );
   charQue.push_back(
' ' );
   charQue.push_back(
' D ' );
   charQue.push_back(
' E ' );
   charQue.push_back(
' ' );
   charQue.push_back(
' G ' );
   charQue.push_back(
' ' );
   charQue.push_back(
' ' );
   charQue.push_back(
' F ' );
   charQue.push_back(
' ' );
   charQue.push_back(
' ' );
   charQue.push_back(
' ' );
   CreateBiTree(root,charQue);
PostOrderTraverse(root);
   cout
<< " 后序遍历结束 " << endl;
   PostOrderTraverseByStack(root);
   cout
<< " 借助于栈的后序遍历结束 " << endl;
   DestroyTree(root);
   cout
<< " 删除树完毕 " << endl;
   cout
<< " finish " << endl;
int f;
   cin
>> f;
return 0 ;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值