二叉树的递归遍历和非递归遍历(C++)

二叉树的遍历方式可分为先序遍历,中序遍历和后序遍历

  • 先序遍历:先遍历根节点,再遍历左子节点,最后遍历右子节点。

  • 中序遍历:先遍历左子节点,再遍历根节点,最后遍历右子节点。

  • 后序遍历:先遍历左子节点,再遍历右子节点,最后遍历根节点。

    区分二叉树的遍历方式的快捷方法:
    看根节点在遍历顺序的前面,中间或者后面:
    根左右(先序),左根右(中序),左右根(后序)

    如图所示为一棵二叉树:

1
2
3
4
5
6
7
  • 先序遍历:1 2 4 5 3 6 7
  • 中序遍历:4 2 5 1 6 3 7
  • 后序遍历:4 5 2 6 7 3 1

1.二叉树的递归遍历代码实现

树节点代码表示

struct TreeNode
{int val;TreeNode* left;TreeNode* right;TreeNode(int x) :left(NULL), right(NULL){this->val=x;}//初始化
};

1.1先序遍历

先遍历根节点,再遍历左子节点,若左子节点存在左子节点或右子节点,则将该左子节点看作根节点继续按照先序遍历的顺序遍历该左子节点为根节点的子树,依次循环,构成递归。

- 先序遍历代码实现

void showTreeNode(TreeNode* root) {//先序递归遍历if (root==NULL)//递归结束条件{return;}cout << root->val;//先打印当前根节点showTreeNode(root->left);//再访问当前节点的左子节点及其子树showTreeNode(root->right);//最后访问当前节点的右子节点及其子树}

1.2中序遍历

同上

void showTreeNode(TreeNode* root) {//中序递归遍历if (root==NULL){return;}showTreeNode(root->left);//先访问当前节点的左子节点及其子树cout << root->val;//再打印当前节点showTreeNode(root->right);//最后访问当前节点的右子节点及其子树}

1.3后序遍历

void showTreeNode(TreeNode* root) {//后序递归遍历if (root==NULL){return;}showTreeNode(root->left);//先访问当前节点的左子节点及其子树showTreeNode(root->right);//再访问当前节点的右子节点及其子树cout << root->val;//最后打印当前节点}

2.二叉树的非递归遍历代码实现

进行二叉树的非递归遍历时,可以利用栈的先进后出的特性去实现。

2.1先序遍历

根据先序遍历的特点,结合栈的特性,先序遍历二叉树最关键的点在于
先打印当前遍历的节点再入栈

  • 代码实现
void NoRecursionTraversal(TreeNode* root)//先序遍历非递归
{   stack<TreeNode*> sta;TreeNdoe* p=root;//辅助指针,表示当前节点指针while(p!=NULL||!sta.empty())//只要当前指针不为空或者栈不为空,循环则可继续{/*先遍历打印当前结点并将当前结点入栈,然后将当前结点变更为当前结点的左子结点,继续打印左子结点并入栈结点为空时则跳出循环*/while(p!=NULL){cout<<p->val;//打印sta.push(p);//入栈p=p->left;}//先将所有左子节点打印并入栈/*当栈不为空时,将p指向栈顶元素保存栈顶元素,出栈后,并将p指向p的右子结点*/if(!sta.empty()){p=sta.top();sta.pop();p=p->right;}//将左子节点出栈并指向右子结点去遍历}
}

2.2中序遍历

中序遍历非递归跟先序遍历大致相同,只不过中序遍历则是采用:
先入栈,后出栈再打印

  • 代码实现
void NorecursionTraversal(NodeTree* root)//中序遍历非递归
{stack<TreeNode*> sta;TreeNdoe* p=root;//辅助指针,表示当前节点指针while(p!=NULL||!sta.empty()){while(p!=NULL){sta.push(p);//入栈p=p->left;}p=sta.top();//获取栈顶元素sta.pop();//出栈cout<<p->val;//打印p=p->right;}
}

2.3后序遍历

后序遍历比先序和中序要复杂一些需要一个辅助变量来记录右子结点是否被访问过,大致思路为:

  • 定义一个辅助指针变量tmp,记录右子结点是否被访问过

    • 如果当前节点存在则将当前结点压栈,并将当前节点指向当前节点的左子节点
    • 栈内元素出栈前先获取栈顶元素,并将p指向栈顶元素
    • 判断p的右子节点是否存在且是否被访问过,如果右子结点为空,则打印当前节点并出栈,未被访问且存在右子结点,则将当前节点指向当前节点的右子结点
    • 将tmp指向p,记录当前节点被访问过,并将p指向NULL
    • 循环上述过程
void NorecursionTraversal(TreeNode* root)
{   stack<TreeNode*> sta;TreeNode* tmp=NULL;//辅助指针,记录当前节点的右子节点是否被访问过TreeNode* p=root;while(p!=NULL||!sta.empty()){  if(p!=NULL){sta.push(p);p=p->left;}else{p=sta.top();if(p->right!=NULL&&tmp!=p->right){p=p->right;}else{cout<<p->val;sta.pop();tmp=p;//记录当前节点被访问过p=NULL;//将p置空,使得p能够访问栈顶}}}
}

这里—>二叉树的层次遍历(宽度优先遍历)

二叉树的递归遍历和非递归遍历实现(C++)(深度优先)相关推荐

  1. 漫谈二叉树遍历(非递归)

    ------这篇文章旨在提出一种简单方便,易于理解时空复杂度低且风格统一的二叉树非递归遍历方法. 从二叉树先序遍历开始 二叉树的先序遍历(非递归)相比中后序是最少花哨.最统一的.一般来说先序遍历的代码 ...

  2. 4.二叉树的先序、中序以及后序遍历的递归写法与非递归写法(LeetCode第94、144、145题)

    一.递归法 这次我们要好好谈一谈递归,为什么很多同学看递归算法都是"一看就会,一写就废". 主要是对递归不成体系,没有方法论,每次写递归算法 ,都是靠玄学来写代码,代码能不能编过都 ...

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

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

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

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

  5. 算法练习day10——190328(二叉树的先序、 中序、 后序遍历, 包括递归方式和非递归方式、找到一个节点的后继节点、二叉树的序列化和反序列化)

    1.实现二叉树的先序. 中序. 后序遍历, 包括递归方式和非递归方式 1.1 访问节点的顺序 节点访问顺序如下图所示: 访问顺序:1 2 4 4 4 2 5 5 5 2 1 3 6 6 6 3 7 7 ...

  6. 信号放大器数据结构_[11/11]数据结构 二叉树应用(树型信号放大器,file transfer,遍历的非递归实现)...

    树型分布网络信号放大器 森林和二叉树的相互转换 并查集 例题:File transfer #include <iostream> using namespace std; //typede ...

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

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

  8. 二叉树先中后序递归遍历与非递归遍历、层次遍历

    文章目录 1 先序遍历 1.1 先序遍历递归 1.2 先序遍历非递归 2 中序遍历 2.1 中序遍历递归 2.2 中序遍历非递归 3 后序遍历 3.1 后序遍历递归 3.2 后序遍历非递归 4 层序遍 ...

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

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

  10. 二叉树的遍历(非递归)整理

    二叉树的遍历(非递归) 写在前面 二叉树重要,重要,重要.以下代码每日手撸一遍,深刻理解. 二叉树的先序遍历(非递归) 巧记心法 判断是否为空树 1.右侧入栈(访问,q指向右孩子,不空则入栈) 2.p ...

最新文章

  1. python基础知识点-Python入门基础知识点(基础语法介绍)
  2. 听说,当使用Reactjs的时候,Gulp和Browserify很配哦
  3. find linux 指定后缀_linux下find(文件查找)命令的用法总结
  4. 源于 Node.js的HTML 模板引擎Jade的一个hello world项目
  5. C++实现树的基本操作,界面友好,操作方便,运行流畅,运用模板
  6. css3弧形跑道效果_Css 实现漂亮弧形
  7. 【备忘】二叉树遍历的迭代实现
  8. 九校联考-长沙市一中NOIP模拟总结
  9. 微信小游戏代码包侵权(最新)
  10. 华硕点亮系统无法连接到服务器,华硕点亮点亮后台管理系统
  11. mysql 定时任务 日志_mysql定时备份任务
  12. python黑马视频全套-2018年6月北京黑马python24期全套视频课程
  13. http://baiy.cn/doc/cpp/index.htm#代码风格与版式_函数
  14. matlab 画qpsk眼图,MATLABQPSK在AWGN信道下的仿真
  15. 一篇文章看懂Facebook和新浪微博的智能FEED
  16. 集中派发福利:《神秘的程序员们》年度大抽奖
  17. 太阳能电池系统行业调研报告 - 市场现状分析与发展前景预测
  18. IPv4子网划分与聚合
  19. 1299: 【二分查找】找球号
  20. SQL Server 【附】创建商品管理数据库、学生选课数据库的SQL语句

热门文章

  1. 路由表中preference 和metric的含义
  2. 汽车变速箱前后面孔系钻削攻丝组合机床设计 (生产率计算卡 论文 CAD图纸……)
  3. 阿里quick_bi和biee报表工具的对比
  4. 【UE4】视角制作相关知识点(蓝图)
  5. 为什么文本乱码呢,我来告诉你什么是编码,解码,乱码
  6. 超经典的20道SQL题目(附加解题思路)
  7. Java Integer128陷阱详解
  8. vue中读取文本文件内容_vue中读取本地文件
  9. 关于模拟器adb 端口查看
  10. 神经网络应用实例 -- python