非递归、仅用一个栈、不加标记数组实现二叉树的后序遍历算法

作者: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);

pOldTop=pNewTop;

flag=0;

}

 

}

 

}

 

 

 

}

 

}

 

 

第三步:代码实现
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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值