二叉树的遍历 (递归实现)

用C++实现二叉树的“先根遍历”存储。

用C++实现二叉树的“先根遍历”、“中根遍历”、“后根遍历”分别输出二叉树中结点的数据。

#include <iostream>
using namespace std ;struct BiNode
{char data ;BiNode *lchild , *rchild ;
} ;
BiNode *BiTree ;int NodeID ;BiNode *CreateBiTree (char *c , int n)
{BiNode *T ;NodeID ++ ;if (NodeID > n){return (NULL) ;}if (c[NodeID] == '0'){return (NULL) ;}T = new BiNode ;T -> data = c[NodeID] ;T -> lchild = CreateBiTree (c , n) ;T -> rchild = CreateBiTree (c , n) ;return (T) ;
}void PreOrderTraverse (BiNode *T)
{if (T){cout << T -> data << " ";PreOrderTraverse (T -> lchild) ;PreOrderTraverse (T -> rchild) ;}
}void InOrderTraverse (BiNode *T)
{if (T){InOrderTraverse (T -> lchild) ;cout << T -> data << " ";InOrderTraverse (T -> rchild) ;}
}void PostOrderTraverse (BiNode *T)
{if (T){PostOrderTraverse (T -> lchild) ;PostOrderTraverse (T -> rchild) ;cout << T -> data << " ";}
}int main ()
{int i , SampleNum ;char c[100] ;cin >> SampleNum ;for (i = 1 ; i <= SampleNum ; i ++){cin >> c[i] ;}NodeID = 0 ;BiTree = CreateBiTree (c , SampleNum) ;PreOrderTraverse (BiTree) ;cout << endl ;InOrderTraverse (BiTree) ;cout << endl ;PostOrderTraverse (BiTree) ;return 0 ;
}

C++实现的非递归版本代码

struct BinaryTreeNode {int val;BinaryTreeNode* leftchild;BinaryTreeNode* rightchild;BinaryTreeNode(int const& _val, BinaryTreeNode* _leftchild=NULL, BinaryTreeNode* _rightchild=NULL) :val(_val), leftchild(_leftchild), rightchild(_rightchild) {}};

三种遍历方式  访问节点的顺序是一致的,不同之处在于,有的遍历流程把访问到的节点暂存起来,达成某种条件后再将节点输出。约定, 根节点V, 其左孩子为L, 右孩子为R, 那么遍历顺序可以记为:

Pre-Order Traversal : 到达一个节点后,即刻输出该节点的值,并继续遍历其左右子树。                                VLR

In-Order Traversal  :   到达一个节点后,将其暂存,遍历完左子树后,再输出该节点的值,然后遍历右子树。LVR

Post-Order Traversal:   到达一个节点后,将其暂存,遍历完左右子树后,再输出该节点的值。                          LRV

                                          

Pre-Order Traversal                                          In-Order Traversal                                          Post-Order Traversal

先序遍历

先序遍历与中序、后序遍历都使用了栈结构来暂存节点

void pre_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> node_stack;       //用来暂存节点的栈while (root != nullptr || !node_stack.empty()) {if (root != nullptr) {                     //若当前的节点非空std::cout << root->val << " ";         //则输出该节点的值node_stack.push(root);                 //该节点压入栈中root = root->leftchild;                //继续向左子树前进}else {root = node_stack.top();               //取栈顶节点root = root->rightchild;               //继续向右子树前进node_stack.pop();                      //删除栈顶节点}}}

中序遍历

与先序遍历类似,唯一区别是到达当前节点时  并不直接输出该节点。

void in_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> stack_node;while (root != nullptr || !stack_node.empty()) {if (root != nullptr) {stack_node.push(root);      //节点入栈root = root->leftchild;     //继续访问左子树直到底}else {root = stack_node.top();    //取栈顶节点std::cout << root->val << " "; //访问节点数据root = root->rightchild;    //继续向右子树前进stack_node.pop();           //删除栈顶}}
}

后序遍历

与先序、中序遍历有所不同,后序遍历在决定是否可以输出当前节点的值的时候,需要考虑其左右子树是否都已经遍历完成。

因此我们需要设置一个lastvisit游标。若lastvisit等于当前考查节点的右子树,表示该节点的左右子树都已经遍历完成,则可以输出当前节点(否则,继续向右子树进发)。并把lastvisit节点设置成当前节点,将当前游标节点root设置为空,下一轮就可以访问栈顶元素。

void post_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> stack_node;BinaryTreeNode* lastvisit = root;while (root != nullptr || !stack_node.empty()) {if (root != nullptr) {stack_node.push(root);root = root->leftchild;}else {root = stack_node.top();if (root->rightchild == nullptr || root->rightchild == lastvisit) {std::cout << root->val << " ";stack_node.pop();lastvisit = root;root = nullptr;}else {root = root->rightchild;}}}}

下面是测试用的代码:

int main(int argc, char* argv[]) {BinaryTreeNode* A = new BinaryTreeNode(1);BinaryTreeNode* B = new BinaryTreeNode(2);BinaryTreeNode* C = new BinaryTreeNode(4);BinaryTreeNode* D = new BinaryTreeNode(7);BinaryTreeNode* E = new BinaryTreeNode(3);BinaryTreeNode* F = new BinaryTreeNode(5);BinaryTreeNode* G = new BinaryTreeNode(6);BinaryTreeNode* H = new BinaryTreeNode(8);A->leftchild = B;A->rightchild = E;B->leftchild = C;C->rightchild = D;E->leftchild = F;E->rightchild = G;G->leftchild = H;std::cout << "Pre order traversal:" << std::endl;pre_traversal(A);std::cout << std::endl<< "In order traversal:" << std::endl;in_traversal(A);std::cout << std::endl << "Post order traversal:" << std::endl;post_traversal(A);return 0;
}

二叉树的遍历 (递归和非递归实现)相关推荐

  1. 二叉树的非递归遍历(递归和非递归)

    二 叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就是 递归定义,因此采用递归的方法去实现树的三种遍历不仅 ...

  2. 遍历二叉树的各种操作(非递归遍历)

    先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序.中序.后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组 ...

  3. 二叉树的几种递归和非递归式遍历:

    二叉树的几种递归和非递归式遍历: 1 #include <fstream> 2 #include <iostream> 3 4 using namespace std; 5 6 ...

  4. 分别用递归和非递归方式实现二叉树先序、中序和后序遍历(java实现)

    分别用递归和非递归方式实现二叉树先序.中序和后序遍历 用递归和非递归方式,分别按照二叉树先序.中序和后序打印所有的节点.我们约定:先序遍历顺序 为根.左.右;中序遍历顺序为左.根.右;后序遍历顺序为左 ...

  5. 二叉树的递归和非递归遍历

    二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易 ...

  6. 二叉树路径应用举例(基于非递归后序遍历)

    #include "stdafx.h" #include <iostream> #include <fstream>using namespace std; ...

  7. 转载:二叉树的前中后和层序遍历详细图解(递归和非递归写法)

    二叉树的前中后和层序遍历详细图解(递归和非递归写法) Monster_ii 2018-08-27 17:01:53 50530 收藏 403 分类专栏: 数据结构拾遗 文章标签: 二叉树 前序 中序 ...

  8. 九十五、二叉树的递归和非递归的遍历算法模板

    @Author:Runsen 刷Leetcode,需要知道一定的算法模板,本次先总结下二叉树的递归和非递归的遍历算法模板. 二叉树的四种遍历方式,前中后加上层序遍历.对于二叉树的前中后层序遍历,每种遍 ...

  9. 二叉树层序遍历递归与非递归_二叉树基础(1)-构建和遍历(递归和非递归)...

    二叉树的构建有2种方式:1.直接输入数字.2.根据两种顺序来判断另外一中顺序(后面会提到) 这里分享第一种构建方式,二叉树的前中后三种遍历方式(递归和非递归版本),和二叉树的层次遍历. 见代码demo ...

  10. 二叉树的遍历:先序 中序 后序遍历的递归与非递归实现及层序遍历

    二叉树的定义:一种基本的数据结构,是一种每个节点的儿子数目都不多于2的树 树节点的定义如下: // 树(节点)定义 struct TreeNode {int data; // 值TreeNode* l ...

最新文章

  1. 汪国华 基因组分析的生物信息学算法
  2. 来跟我一起分享技术、传递价值:阿里云MVP全球招募,火热启动!
  3. Play Framework 2.2.6 安装
  4. 1109: 数根(函数专题)
  5. 今天一看,自己发的文章原来这么多了。openeim
  6. STM32 HAL库 UART 串口读写功能笔记
  7. leetcode 102 java_Java实现 LeetCode 102 二叉树的层次遍历
  8. java对redis的基本操作(初识)
  9. iOS开发实战小知识点(四)
  10. 二叉搜索树相关性质的应用
  11. python画3d图-python3利用Axes3D库画3D模型图
  12. 智能制造与数字化工厂
  13. android studio打包h5,Android Studio打包生成APK教程
  14. python 两个nc文件 风场,ECMWF 不同step 的 NC 文件如何合并
  15. 图解大数据 | Spark GraphFrames-基于图的数据分析挖掘
  16. 逃离北上广:你以为回到小城市就很幸福了吗?
  17. 等差数列_等比数列公式
  18. SpringBoot初学笔记(SpringBoot实战之数据库相关操作)
  19. Spring IoC容器与Bean管理18:Bean对象的作用域及生命周期三:对象生命周期;
  20. ORBSLAM2单应矩阵计算及代码分析

热门文章

  1. HTML页面显示缩略所有空格为一格的方法
  2. 个人阅读 代码大全的阅读与提问
  3. 若一个月给你50000元,要你选下面一件事做,你会选?
  4. 面试ASP.NET程序员的笔试题和机试题(转,有点意思,答案不是很标准)
  5. [数据库] Navicat for MySQL换种思维解决插入同时更新数据
  6. RxSwift之UI控件UISlider与UIStepper扩展的使用
  7. iOS开发常用的资源和资料
  8. 面试题 08.03. Magic Index LCCI 魔术索引
  9. 152. 乘积最大子数组
  10. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言—— 1066:满足条件的数累加