剑指offer——复习1:二叉树三种遍历方式的迭代与递归实现
剑指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:二叉树三种遍历方式的迭代与递归实现相关推荐
- 剑指 Offer 05. 替换空格 三种方法
剑指 Offer 05. 替换空格(点击立即答题) 请实现一个函数,把字符串 s 中的每个空格替换成"%20". 示例 1: 输入:s = "We are happy.& ...
- 二叉树三种遍历方式的非递归实现
树的递归实现方式很简单,下面介绍三种遍历的非递归实现. 树的遍历有个特点,那就是在处理具体问题时,绝大多数情况下是在当前循环.或函数(或是子树)的根节点来处理的,能够注意到当前根节点是如何从上个根节点 ...
- 二叉树三种遍历方式,先序、中序、后序
二叉树遍历方式分为三种:先序,中序和后序. 可以以根节点的位置为参考来记遍历方式,在第一个为先序,中间为中序,最后为后序: 即:先序: 根左右:中序:左根右:后序:左右根. 借个图: 之前看过一个视频 ...
- 二叉树的三种遍历方式:前序遍历、中序遍历和后序遍历
二叉树的三种遍历方式:前序遍历.中序遍历和后序遍历 参考资料: 二叉树.前序遍历.中序遍历.后序遍历 - 蓝海人 - 博客园 (cnblogs.com) 二叉树 - LeetBook - 力扣(Lee ...
- 二叉树的三种遍历方式(递归、非递归和Morris遍历)
二叉树的三种遍历方式(递归.非递归和Morris遍历) 原文:http://www.linuxidc.com/Linux/2015-08/122480.htm 二叉树遍历是二叉树的最基本的操作,其实现 ...
- 二叉树的前序中序后序三种遍历方式及递归算法介绍
二叉树三种遍历方式 二叉树的遍历是整个二叉树的核心,二叉树的几本操作都要依赖于遍历,对于二叉树的遍历,递归是最简单也最容易理解的,本文详细介绍了二叉树的三种遍历方法,并用递归来实现: 完整的可调试代码 ...
- 【LeetCode】剑指 Offer 68 - II. 二叉树的最近公共祖先
[LeetCode]剑指 Offer 68 - II. 二叉树的最近公共祖先 文章目录 [LeetCode]剑指 Offer 68 - II. 二叉树的最近公共祖先 一.DFS 一.DFS 祖先的定义 ...
- 【LeetCode】剑指 Offer 37. 序列化二叉树
[LeetCode]剑指 Offer 37. 序列化二叉树 文章目录 [LeetCode]剑指 Offer 37. 序列化二叉树 package offer;import java.util.Link ...
- 【LeetCode】剑指 Offer 07. 重建二叉树
[LeetCode]剑指 Offer 07. 重建二叉树 文章目录 [LeetCode]剑指 Offer 07. 重建二叉树 package offer;import java.util.ArrayD ...
最新文章
- 五分钟让你了解 Java方法(或者叫函数)
- Spring3.0 AOP 具体解释
- linux重点知识:网络通信
- 使用MyEclipse构建MAVEN项目 - 我的漫漫程序之旅 - BlogJava
- Ubuntu 16.04安装SQLite Browser操作SQLite数据库
- 我的docker随笔29:oracle数据库部署
- ASR开发工作笔记0002---认识iccid
- 附录-系统环境、系统属性
- Mysql 性能优化——必胜之道
- win10一直正在检查更新_Win10关闭自动更新的方法汇总
- iphone如何删除“不可删除”的描述文件?(桌面快捷方式web clib)
- Python自动化办公实战:包含Word、Excel、Pdf和Email邮件案例
- 2017年大数据会是广告市场最后一根救命草吗?
- U盘不被电脑识别问题
- 基于浙大MO平台的开发机器学习算法
- webERP开源系统安装配置
- jenkins 创建用户角色项目权限
- ILSpy反编译C#web程序
- SpringBoot在IDEA中同一个项目用不同端口启动
- 直男 or Gay?看看你的DNA标记!
热门文章
- vb子程序未定义怎么改怎么办_vb中总提示子程序或函数未定义
- 手机java环境_手机端搭建Java编译运行环境
- nbu备份oracle rac,利用NETBACKUP将备份写到磁盘上
- 64位装32位oracle软件,在64位linux下安装32位oracle软件
- springboot传入json和文件_Spring Boot之 Controller 接收参数和返回数据总结(包括上传、下载文件)...
- 使用promise解决回调地狱_回调地狱的由来和如何利用promise解决回调地狱
- 潜流式人工湿地计算_「环保技术」农村混合污水人工湿地处理
- php iis user,IIS+PHP环境的./路径问题
- anaconda和python有什么不一样_看着一样的胶带,价格为什么不一样?
- 新建oracle数据库 环境查询,Oracle单实例数据库迁移到Oracle RAC 环境之(2)--实施篇...