博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前序-中序-后序-非递归-实现
阅读量:6487 次
发布时间:2019-06-24

本文共 2106 字,大约阅读时间需要 7 分钟。

1. 简述

    前序,根->左子树->右子树,中序,左子树->根->右子树,后序,左子树->右子树->根。

    本文主要关注三种遍历方式的非递归实现。其中,中序和后序的实现来自参考中的“二叉树的遍历:前序,中序,后序,层序--包括递归和非递归实现”一文及其评论,前序比较简单,单独写了个实现与参考的文中实现不同。另外,对于中序和后序,实现是一样的,也没什么意思,加了几行注释,就这样了,实现主要是核心代码,完整代码在参考的文章中很详细。
2. 前序非递归
    首先,栈顶元素入栈,然后进入循环,每次把栈顶元素输出,元素出栈,将该元素的右孩子(如果存在)和左孩子(如果存在)依次入栈。 

void
 PreOrder(Node
*
 root) {
  assert(NULL != root)
  stack
<
Node
*>
 store;
  store.push(root); 
//
 根结点入栈 
  
while
(
!
store.empty()) { 
    root
=
 store.top(); // 在循环中,root记录的是当前准备输出的结点
    store.pop();
    cout 
<<
 root
->
value 
<<
 
"
  
"
//
 输出当前结点 
    
if
(root
->
right_child) 
//
 右孩子入栈 
      store.push(root
->
right_child);
    
if
(root
->
left_child) 
//
 左孩子入栈 
      store.push(root
->
left_child); 
  }
}

3. 中序非递归

    前序中的Root主要作为中间变量使用。这里的Root的意义是下一个要进栈的结点,初始值为根结点。

    while (Root不为空 || 栈不为空) {
         if(Root不为空) // 一路向左入栈 
             Root入栈
             Root=Root->left_child。
         else // 栈顶元素的左子树都输出过了
             输出栈顶元素
             Root=栈顶元素->right_child
             栈顶元素出栈。

    }  

void
 InOrder(Node
*
 root) {
  assert(NULL 
!=
 root);
  stack
<
Node
*>
 store;
  
while
(root 
&&
 
!
store.empty()) {
    
if
(root 
!=
 NULL) { 
//
 只要不为空,就一路向左结点方向走去 
      store.push(root);
      root 
=
 root
->
left_child;
    }
    
else
 { 
//
 store.top()的左边都走过了 
      cout 
<<
 store.top()
->
value 
<<
 
"
  
"
//
 输出当前结点 
      root 
=
 store.top()
->
right_child;
      store.pop();
    }
  }
}

4. 后序非递归

    Root表示下一个要处理的结点,初始化为根结点,Per表示上一次刚刚输出过的结点。

,Per的作用是对有孩子的结点进行判断,由于算法特性,每次到某个结点时,其左子树都输出过了,此时只要判断Pre是否是当前结点的右孩子,如果不是,那么说明其右子树没走过,那么Root=当前结点的右子树,否则就是刚刚输出了当前结点的右孩子,由于是后序,其右子树也必定都输出过了,此时只要输出当前结点,更新Pre就好了。
    while(Root不为空 || 栈不为空) {
         if(Root不为空) // 一路向左
            Root入栈
            Root=Root->left_child
         else { // 此时栈顶元素的左子树都输出过了
             Root = 栈顶元素
             if(Root有右孩子 && Pre不等于Root的右孩子) // 此时栈顶元素的右子树还没输出
                 Root=Root->right
             else // 此时栈顶元素的左右子树都输出过了
                 输出栈顶元素
                 Pre = 栈顶元素
                 栈顶元素出栈                 
          }

    }

void
 PostOrder(Node
*
 root) {
  assert(NULL 
!=
 root);
  Node
*
 Pre 
=
 NULL;
  stack
<
Node
*>
 store;
  
while
(root 
&&
 
!
store.empty()) {
    
if
(root 
!=
 NULL) { 
//
 一路向左 
      store.push(root);
      root 
=
 root
->
left_child;
    }
    
else
 { 
//
 stack.top()的左子树都输出完了 
      
if
(store.top()
->
right_child
!=
NULL 
&&
 store.top()
->
right_child
!=
Pre) { 
      
//
 右子树存在且没有输出过 
        root 
=
 root
->
right_child; 
      } 
      
else
 { 
//
 左右子树都输出过了 
        cout 
<<
 store.top()
->
value 
<<
 
"
  
"
;
        Pre 
=
 store.top();
        store.pop(); 
      } 
    }
  }

 

5. 参考

    二叉树的遍历:前序,中序,后序,层序--包括递归和非递归实现

   

转载地址:http://onauo.baihongyu.com/

你可能感兴趣的文章
Exchange 2010的部署
查看>>
notes 临时文件
查看>>
大表之困惑 - 数据建模的前期规划十分重要
查看>>
***团体Anonymous黑美智库 盗百万美元做慈善
查看>>
分支+循环
查看>>
基于算法的建模---形状语法核其他过程方法
查看>>
Java语言概述
查看>>
我的友情链接
查看>>
MySQL服务器Swap满了100%导致db很慢很卡
查看>>
我的友情链接
查看>>
关于Delphi XE2的FMX的一点点研究之消息篇
查看>>
OSPF-LSU
查看>>
Linux忘记root密码怎么办?简简单单教你自己解决!
查看>>
“5410台 全千兆网络回路故障排除”
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
澳安全局淡定回应***袭击
查看>>
点击图片实现放大镜效果
查看>>
centos6.6升级openssh到最新版本7.5.p1
查看>>
yum源部署LNMP及简介
查看>>