剑指offer——复习1:二叉树三种遍历方式的迭代与递归实现

20180905更新:这个博客中的解法不是很好,看相应的LeetCode题目笔记~~~
我感觉此博客中的说法更容易让人理解:https://blog.csdn.net/woshinannan741/article/details/52825163,还是看这个博客比较好,下面的内容不是很好理解啊。。
本博客转载自:https://blog.csdn.net/xiaominkong123/article/details/51567437
二叉树的三种遍历为:前序遍历,中序遍历和后序遍历。
遍历的实现可分为递归和非递归。递归法与二叉树的定义相似,非递归法采用栈去模拟实现。
定义树节点

struct BinaryTreeNode {int val;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
};

一、前序遍历

遍历的次序为:根结点——左结点——右结点。

递归

//前序遍历的递归实现
void Pre_travel1(BinaryTreeNode* pRoot) {  if(pRoot == NULL)return;  cout<< pRoot->val << endl;  if(pRoot->left != NULL)  Pre_travel1(pRoot->left);  if(pRoot->right != NULL)  Pre_travel1(pRoot->right);
}  

非递归

前序遍历的访问顺序为:根,左和右。对于任一结点,其可看做根结点,因此可直接访问。访问完后,若其左孩子不为空,则按照相同规则访问它的左子树;访问完左子树,再访问它的右子树。处理过程如下:
对于任一结点P:
step 1:访问结点p,并将结点p入栈。
step 2:判断结点p的左孩子是否为空。若为空,则取栈顶结点并出栈,将栈顶元素的右孩子设为当前的结点p,循环至 第1步。若不为空,则将p的左孩子设为当前结点p。
step 3:直到p为NULL,并且栈为空,则遍历结束。

//前序遍历的非递归遍历
void Pre_travel2(BinaryTreeNode* pRoot) {  stack<BinaryTreeNode*> s;  BinaryTreeNode *p = pRoot;  if(pRoot == NULL)  return;  while(p != NULL || !s.empty()) {  while(p != NULL) {  cout << p->val << endl;  s.push(p);  p=p->left;  }  if(!s.empty()) {  p=s.top();  s.pop();  p=p->right;  }  }
}  

二、中序遍历

遍历的次序为:左结点——根结点——右结点。

递归

//中序遍历的递归实现
void Inorder_travel1(BinaryTreeNode* pRoot) {  if(pRoot == NULL)return;if(pRoot->left != NULL)  Inorder_travel1(pRoot->left);  cout<< pRoot->val << endl;      if(pRoot->right != NULL)  Inorder_travel1(pRoot->right);
}  

非递归

根据中序遍历的顺序,对于任一结点,先访问其左孩子。而左孩子又可以看做一个根结点,然后继续访问左孩子,直到遇到的左孩子结点为空,则停止访问。然后访问右孩子。
处理过程如下:
对于任一结点p:
step 1:若其左孩子不为空,则将p入栈,并将p的左孩子置为当前的p。然后对当前结点p再进行相同的处理。
step 2:若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将栈顶结点的右孩子置为当前的P结点。
step 3:直到p为NULL并且栈为空则遍历结束。

//中序遍历的非递归法
void Inorder_travel2(BinaryTreeNode* pRoot) {  stack<BinaryTreeNode*> s;  BinaryTreeNode *p = pRoot;  while(p != NULL || !s.empty()) {  while(p!=NULL) {  s.push(p);  p=p->left;  }  if(!s.empty()) {  p=s.top();  cout << p->value <<endl;  s.pop();  p=p->right;  }  }
}  

三、后序遍历

遍历的次序为:左结点——右结点——根结点。

递归

//后序遍历的递归实现
void Postorder_travel1(BinaryTreeNode* pRoot) {  if(pRoot == NULL)return;if(pRoot->left != NULL)  Postorder_travel1(pRoot->left);  if(pRoot->right != NULL)  Postorder_travel1(pRoot->right);  cout<< pRoot->val << endl;
}  

非递归

非递归遍历:要保证根结点在左孩子和右孩子访问之后才能访问。因此对于任一结点p,先将其入栈。
若p不存在左孩子和右孩子,则可以直接访问它。或者p存在左孩子或者右孩子,但是左孩子和右孩子都已经被访问过了,则可以直接访问该结点。
若非上述两种情况,则将右孩子和左孩子依次入栈。这样可以保证每次取栈顶元素时,左孩子在右孩子前面被访问,根结点在左孩子和右孩子访问之后被访问。

//后序遍历的非递归法
void Postorder_travel2(BinaryTreeNode* pRoot) {  stack<BinaryTreeNode*> s;  BinaryTreeNode *cur;  BinaryTreeNode *pre=NULL;  s.push(pRoot);//根结点入栈  while(!s.empty()) {  cur=s.top();  if((cur->left==NULL&&cur->right==NULL)||(pre!=NULL&&(pre==cur->left||pre==cur->right))) {  //左孩子和右孩子同时为空,或者当前结点的左孩子或右孩子已经遍历过了  cout << cur->value << endl;  s.pop();  pre=cur;  }  else {  if(cur->right!=NULL)  s.push(cur->right);  if(cur->left!=NULL)  s.push(cur->left);  }  }
}  

关于层次遍历参考链接:剑指offer——面试题60:把二叉树打印成多行
https://blog.csdn.net/allenlzcoder/article/details/79785180

剑指offer——复习1:二叉树三种遍历方式的迭代与递归实现相关推荐

  1. 剑指 Offer 05. 替换空格 三种方法

    剑指 Offer 05. 替换空格(点击立即答题) 请实现一个函数,把字符串 s 中的每个空格替换成"%20". 示例 1: 输入:s = "We are happy.& ...

  2. 二叉树三种遍历方式的非递归实现

    树的递归实现方式很简单,下面介绍三种遍历的非递归实现. 树的遍历有个特点,那就是在处理具体问题时,绝大多数情况下是在当前循环.或函数(或是子树)的根节点来处理的,能够注意到当前根节点是如何从上个根节点 ...

  3. 二叉树三种遍历方式,先序、中序、后序

    二叉树遍历方式分为三种:先序,中序和后序. 可以以根节点的位置为参考来记遍历方式,在第一个为先序,中间为中序,最后为后序: 即:先序: 根左右:中序:左根右:后序:左右根. 借个图: 之前看过一个视频 ...

  4. 二叉树的三种遍历方式:前序遍历、中序遍历和后序遍历

    二叉树的三种遍历方式:前序遍历.中序遍历和后序遍历 参考资料: 二叉树.前序遍历.中序遍历.后序遍历 - 蓝海人 - 博客园 (cnblogs.com) 二叉树 - LeetBook - 力扣(Lee ...

  5. 二叉树的三种遍历方式(递归、非递归和Morris遍历)

    二叉树的三种遍历方式(递归.非递归和Morris遍历) 原文:http://www.linuxidc.com/Linux/2015-08/122480.htm 二叉树遍历是二叉树的最基本的操作,其实现 ...

  6. 二叉树的前序中序后序三种遍历方式及递归算法介绍

    二叉树三种遍历方式 二叉树的遍历是整个二叉树的核心,二叉树的几本操作都要依赖于遍历,对于二叉树的遍历,递归是最简单也最容易理解的,本文详细介绍了二叉树的三种遍历方法,并用递归来实现: 完整的可调试代码 ...

  7. 【LeetCode】剑指 Offer 68 - II. 二叉树的最近公共祖先

    [LeetCode]剑指 Offer 68 - II. 二叉树的最近公共祖先 文章目录 [LeetCode]剑指 Offer 68 - II. 二叉树的最近公共祖先 一.DFS 一.DFS 祖先的定义 ...

  8. 【LeetCode】剑指 Offer 37. 序列化二叉树

    [LeetCode]剑指 Offer 37. 序列化二叉树 文章目录 [LeetCode]剑指 Offer 37. 序列化二叉树 package offer;import java.util.Link ...

  9. 【LeetCode】剑指 Offer 07. 重建二叉树

    [LeetCode]剑指 Offer 07. 重建二叉树 文章目录 [LeetCode]剑指 Offer 07. 重建二叉树 package offer;import java.util.ArrayD ...

最新文章

  1. 五分钟让你了解 Java方法(或者叫函数)
  2. Spring3.0 AOP 具体解释
  3. linux重点知识:网络通信
  4. 使用MyEclipse构建MAVEN项目 - 我的漫漫程序之旅 - BlogJava
  5. Ubuntu 16.04安装SQLite Browser操作SQLite数据库
  6. 我的docker随笔29:oracle数据库部署
  7. ASR开发工作笔记0002---认识iccid
  8. 附录-系统环境、系统属性
  9. Mysql 性能优化——必胜之道
  10. win10一直正在检查更新_Win10关闭自动更新的方法汇总
  11. iphone如何删除“不可删除”的描述文件?(桌面快捷方式web clib)
  12. Python自动化办公实战:包含Word、Excel、Pdf和Email邮件案例
  13. 2017年大数据会是广告市场最后一根救命草吗?
  14. U盘不被电脑识别问题
  15. 基于浙大MO平台的开发机器学习算法
  16. webERP开源系统安装配置
  17. jenkins 创建用户角色项目权限
  18. ILSpy反编译C#web程序
  19. SpringBoot在IDEA中同一个项目用不同端口启动
  20. 直男 or Gay?看看你的DNA标记!

热门文章

  1. vb子程序未定义怎么改怎么办_vb中总提示子程序或函数未定义
  2. 手机java环境_手机端搭建Java编译运行环境
  3. nbu备份oracle rac,利用NETBACKUP将备份写到磁盘上
  4. 64位装32位oracle软件,在64位linux下安装32位oracle软件
  5. springboot传入json和文件_Spring Boot之 Controller 接收参数和返回数据总结(包括上传、下载文件)...
  6. 使用promise解决回调地狱_回调地狱的由来和如何利用promise解决回调地狱
  7. 潜流式人工湿地计算_「环保技术」农村混合污水人工湿地处理
  8. php iis user,IIS+PHP环境的./路径问题
  9. anaconda和python有什么不一样_看着一样的胶带,价格为什么不一样?
  10. 新建oracle数据库 环境查询,Oracle单实例数据库迁移到Oracle RAC 环境之(2)--实施篇...