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://www.cppblog.com/ngaut/archive/2006/01/01/2351.aspx

前序-中序-后序-非递归-实现相关推荐

  1. 二叉树的前、中、后的非递归遍历

    题目 实现一个链式存储的二叉树,采用非递归的形式,按照前.中.后序的顺序遍历二叉树. 代码 /** * 二叉树的前.中.后序的非递归遍历 **/#include <iostream> us ...

  2. 二叉树的前、中、后遍历非递归实现

    https://leetcode-cn.com/tag/tree/ 5/ \3 6 / \ / \ 2 4 7 8 144. 二叉树的前序遍历 https://leetcode-cn.com/prob ...

  3. 二叉树前序、中序和后序遍历的非递归实现

    1 二叉树的遍历 1.1 前序遍历 对于每棵子树,先处理根,然后处理左子树,最后处理右子树.根最先访问,所以是前序遍历. 1.2 中序遍历 对于每棵子树,先处理左子树,然后处理根,最后处理右子树.根中 ...

  4. 二叉树的深度(前序 中序 后序 递归非递归搜素)、广度、搜索 C++

    a b c 使用 1 2 3 表示 /* 描述:二叉树的深度(前序 中序 后序 递归非递归搜素).广度.搜索 作者:jz 日期:20140819 */ #include<stdio.h> ...

  5. 【二叉树Java】二叉树遍历前序中序后序遍历的非递归写法

    本文主要介绍二叉树前序中序后序遍历的非递归写法 在探讨如何写出二叉树的前序中序后序遍历代码之前,我们先来明确一个问题,前序中序后序遍历根据什么区分? 二叉树的前序中序后序遍历,是相较根节点说的.最先遍 ...

  6. java中二叉树_Java工程师面试1000题224-递归非递归实现二叉树前、中、后序遍历...

    224.使用递归和非递归实现二叉树的前.中.后序遍历 使用递归来实现二叉树的前.中.后序遍历比较简单,直接给出代码,我们重点讨论非递归的实现. class Node { public int valu ...

  7. 二叉树前中后序遍历的非递归实现以及层次遍历、zig-zag型遍历详解

    前言 二叉树的遍历是一个比较常见的问题,递归实现二叉树的前中后序遍历比较简单,但非递归实现二叉树的前中后序遍历相对有难度.这篇博客将详述如何使用非递归的方式实现二叉树的前中后序遍历,在进行理论描述的同 ...

  8. C++实现二叉树 前、中、后序遍历(递归与非递归)非递归实现过程最简洁版本

    本文并非我所写,是复制的该链接中的内容: 最近学习二叉树,想编程实现递归和非递归的实现方式: 递归的方式就不说了,因为大家的递归程序都一样:但是对于非递归的实现方式, 根据这几天的查阅资料已看到差不多 ...

  9. 二叉树遍历(递归实现前序/中序/后序遍历)

    1. 准备工作 我们先定义一棵普通的二叉树,如下图 2. 前序遍历 通过递归进行遍历: 如果二叉树为空,则操作返回: 如果非空,否则从根结点开始,然后遍历左子树,再遍历右子树. 前序遍历的结果是:AB ...

  10. PAT甲级1119 Pre- and Post-order Traversals (30分):[C++题解]暴搜dfs、前序遍历和后序遍历求中序遍历

    文章目录 题目分析 题目链接 题目分析 分析 给了前序遍历和后序遍历,能够确定根结点,但是左子树和右子树的长度是不确定的.这里采用的解决方案是枚举左子树的结点个数,其实右子树的结点个数也确定了.对于每 ...

最新文章

  1. MPICH3环境配置
  2. 【C++ Primer | 13】课后习题答案
  3. 毕业作文计算机系统与维护,修电脑作文600字
  4. shell 获取家目录_一篇教会你写90%的shell脚本
  5. 培训课程第三期签到和意见发表
  6. 毫米波雷达障碍物检测算法介绍
  7. Useful “ifconfig” Commands to Configure Network Interface in Linux
  8. webpack中file-loader和url-loader的关系
  9. 自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)
  10. CentOS 7 怎样自动连接网络
  11. 推荐一些不错的公众号【二】
  12. golang echo框架案例
  13. SpringBoot+zk+dubbo架构实践(四):sb+zk+dubbo框架搭建(内附源码GitHub地址)
  14. 算法学习系列(MCMC):MCMC采样
  15. 女性手游市场,金矿还是深坑?
  16. 不二越机器人编程手册_NACHI机器人说明书
  17. SMP、NUMA、MPP模型介绍
  18. 【游戏建模全流程】Maya风格化模型制作教程
  19. IntelliJ IDEA设置类注释和方法注释模板
  20. 【unittest学习】unittest框架主要功能

热门文章

  1. RPi 树莓派 DSI 接口研究 MIPI raspberry pi
  2. #pragma multi_compile_fwdbase会增加很多个shader variants
  3. 《人月神话》---1
  4. 阿里云mysql安装
  5. 【转】ANSI与GB2312的编码问题
  6. 第一次用access的数据库是连接字符串问题
  7. P3804 【模板】后缀自动机
  8. 第三课 泛型+反射封装数据库访问层 2019-04-02
  9. Eclipse+pydev+手动安装
  10. fastweixin v1.3.0 发布,极速微信公众号开发框架