遍历二叉树 - 基于递归的DFS(前序,中序,后序)
上节中已经学会了如何构建一个二叉搜索数,这次来学习下树的打印-基于递归的DFS,那什么是DFS呢?

有个概念就行,而它又分为前序、中序、后序三种遍历方式,这个也是在面试中经常会被问到的,下面来具体学习下,用三种遍历方法来遍历上节中的二叉数:

前序遍历:

那对于上面的二叉数用前序遍历,遍历过程如下:
1、先遍历根节点【5】
2、再遍历左子树:

需要注意的是:遍历左右子树时仍然采用前序遍历方法。所以如下:
a、先遍历根节点【3】
b、再遍历左子树,由于只有一个结点则直接打印【1】
c、再遍历右子树,由于只有一个结点则直接打印【4】
3、再遍历右子树:

a、先遍历根节点【8】
b、再遍历左子树:

ba、先遍历根节点【7】
bb、再遍历左子树,由于只有一个结点则直接打印【6】
bc、再遍历右子树,由于木有右子树,递归返回。
c、再遍历右子树,由于木有右子树,递归返回。
至此整个前序遍历结束,结果如:【5】、【3】、【1】、【4】、【8】、【7】、【6】
下面看下代码具体实现,基于上节二叉搜索树的实现,增加一个遍历的方法,其它木变,直接上代码:
public class BinarySearchTree {
TreeNode root = null;
class TreeNode{
int value;
int position;
TreeNode left = null, right = null;
TreeNode(int value, int position){
this.value = value;
this.position = position;
}
}
public void add(int value, int position){
if(root == null){//生成一个根结点
root = new TreeNode(value, position);
} else {
//生成叶子结点
add(value, position, root);
}
}
private void add(int value, int position, TreeNode node){
if(node == null)
throw new RuntimeException("treenode cannot be null");
if(node.value == value)
return; //ignore the duplicated value
if(value < node.value){
if(node.left == null){
node.left = new TreeNode(value, position);
}else{
add(value, position, node.left);
}
}else{
if(node.right == null){
node.right = new TreeNode(value, position);
}else{
add(value, position, node.right);
}
}
}
//打印构建的二叉搜索树
static void printTreeNode(TreeNode node) {
if(node == null)
return;
System.out.println("node:" + node.value);
if(node.left != null) {
printTreeNode(node.left);
}
if(node.right != null) {
printTreeNode(node.right);
}
}
//搜索结点
public int search(int value){
return search(value, root);
}
private int search(int value, TreeNode node){
if(node == null)
return -1; //not found
else if(value < node.value){
System.out.println("Searching left");
return search(value, node.left);
}
else if(value > node.value){
System.out.println("Searching right");
return search(value, node.right);
}
else
return node.position;
}
//二叉树遍历
public void travel(){
travel(root);
}
public void travel(TreeNode node){
if(node == null)
return;
System.out.println(" " + node.value);
travel(node.left);
travel(node.right);
}
public static void main(String[] args) {
BinarySearchTree bst = new BinarySearchTree();
int a[] = { 5, 8, 3, 4, 1, 7, 6};
for(int i = 0; i < a.length; i++){
bst.add(a[i], i);
}
bst.travel();
}
}
编译运行:

由于比较好理解,所以这里就不一一debug遍历方法去了,总之是首先先打印当前结点,之后再递归左右子树,刚好跟前序遍历的定义一样。
中序遍历:

同样对于上面的二叉数用前序遍历,遍历过程如下:
1、先遍历左节点

继续按着左中右的遍历顺序继续对左子树进行遍历,如下:
a、先遍历左节点,由于只有一个结点直接打印【1】
b、再遍历根节点【3】
c、最后再遍历右节点【4】
2、再遍历根节点【5】
3、最后再遍历右节点:

继续按着左中右的遍历顺序继续对右子树进行遍历,如下:
a、先遍历左节点

aa、先遍历左节点【6】
ab、再遍历根节点【7】
ac、最后再遍历右节点,由于木有右节点直接结束递归。
b、再遍历根节点【8】
c、最后再遍历右节点,由于木有右节点直接结束递归。
至此整个中序遍历结束,结果如:【1】、【3】、【4】、【5】、【6】、【7】、【8】
【提示】:有木有发现居然结果成了一组有序的数列,也就是说这又是一种排序的算法:将一组数用组成二叉搜索树之后然后再用中序遍历打印出来,当然这种排序算法不是特别好,只是从这个结果点可以联想到排序算法。
下面看下代码具体实现,比较简单,只需要简单修改travel的打印顺序既可,如下:

编译运行:
,跟预期一致。
后序遍历:

同理,对于上面的二叉数用后序遍历,遍历过程如下:
1、先遍历左节点

继续按着左右中的遍历顺序继续对左子树进行遍历,如下:
a、先遍历左节点,由于只有一个结点直接打印【1】
b、再遍历右节点【4】
c、最后再遍历根节点【3】
2、再遍历右节点

继续按着左右中的遍历顺序继续对右子树进行遍历,如下:
a、先遍历左节点

aa、先遍历左节点【6】
ab、最后再遍历右节点,由于木有右节点直接忽略。
ac、再遍历根节点【7】
b、最后再遍历右节点,由于木有右节点直接结束递归。
c、再遍历根节点【8】
3、最后遍历根节点【5】
至此整个后序遍历结束,结果如:【1】、【4】、【3】、【6】、【7】、【8】、【5】
下面看下代码具体实现,同理只需要简单修改travel的打印顺序既可,如下:

编译运行:
,跟预期一致~
那以上的遍历方法的时间复杂度是多少呢?一个结点只访问一次,自然复杂度是O(n),其中n为结点个数。
遍历二叉树 - 基于递归的DFS(前序,中序,后序)的更多相关文章
- 遍历二叉树 - 基于栈的DFS
之前已经学过二叉树的DFS的遍历算法[http://www.cnblogs.com/webor2006/p/7244499.html],当时是基于递归来实现的,这次利用栈不用递归也来实现DFS的遍历, ...
- 算法进阶面试题03——构造数组的MaxTree、最大子矩阵的大小、2017京东环形烽火台问题、介绍Morris遍历并实现前序/中序/后序
接着第二课的内容和带点第三课的内容. (回顾)准备一个栈,从大到小排列,具体参考上一课.... 构造数组的MaxTree [题目] 定义二叉树如下: public class Node{ public ...
- 二叉树 遍历 先序 中序 后序 深度 广度 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 前序+中序->后序 中序+后序->前序
前序+中序->后序 #include <bits/stdc++.h> using namespace std; struct node { char elem; node* l; n ...
- SDUT OJ 数据结构实验之二叉树八:(中序后序)求二叉树的深度
数据结构实验之二叉树八:(中序后序)求二叉树的深度 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Probl ...
- SDUT-2804_数据结构实验之二叉树八:(中序后序)求二叉树的深度
数据结构实验之二叉树八:(中序后序)求二叉树的深度 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 已知一颗二叉树的中序 ...
- 给出 中序&后序 序列 建树;给出 先序&中序 序列 建树
已知 中序&后序 建立二叉树: SDUT 1489 Description 已知一棵二叉树的中序遍历和后序遍历,求二叉树的先序遍历 Input 输入数据有多组,第一行是一个整数t (t& ...
- 【C&数据结构】---关于链表结构的前序插入和后序插入
刷LeetCode题目,需要用到链表的知识,忽然发现自己对于链表的插入已经忘得差不多了,以前总觉得理解了记住了,但是发现真的好记性不如烂笔头,每一次得学习没有总结输出,基本等于没有学习.连复盘得机会都 ...
- 【11】-java递归和非递归二叉树前序中序后序遍历
二叉树的遍历 对于二叉树来讲最主要.最基本的运算是遍历. 遍历二叉树 是指以一定的次序访问二叉树中的每个结点.所谓 访问结点 是指对结点进行各种操作的简称.例如,查询结点数据域的内容,或输出它的值,或 ...
随机推荐
- eNSP——配置Trunk接口
原理: 在以太网中,通过划分 VLAN 来隔离广播域和增强网络通信的安全性.以太网通常由多台交换机组成,为了使 VLAN 的数据帧跨越多台交换机传递,交换机之间互连的链路需要设置为干道链路( Trun ...
- 洛谷 题解 P2280 【[HNOI2003]激光炸弹】
一道很好的二维前缀和模板题. 什么是二维前缀和? 从这张图可以看出前缀和的求法: Map[i][j]=Map[i-1][j]+Map[i][j-1]-Map[i-1][j-1]+Map[i][j]; ...
- 【转帖】Samba AD DC(域控制器)的配置
Samba AD DC(域控制器)的配置 http://lihaitao.cn/?p=299 山东前辈写的blog 挺好的.. 改天做实验. 发表于2017年3月7日由李海涛 ■Samba AD DC ...
- windows 清理 cbs.log 文件
请参考以下步骤 1.win+r输入 services.msc进入服务,找到并双击Windows Modules Installer点击停止, 2.然后就可以手动删除 3.按一的步骤开启TrustedI ...
- HTTP报文学习
HTTP报文用于HTTP协议的信息交互,分为请求报文和响应报文.报文由首部和主体两部分组成,中间使用空行(CR+LF)分隔 1. 报文结构 报文由首部.空行和实体组成: 报文中首先是请求行或者状态行, ...
- 补码一位乘法 Booth算法 Java简易实现
本文链接:https://www.cnblogs.com/xiaohu12138/p/11955619.html. 转载,请说明出处. 本程序为简易实现补码一位乘法,若代码中存在错误,可指出,本人会不 ...
- VMWare虚拟机15.X局域网网络配置(修改网卡)
最近在搞几台虚拟机来学习分布式和大数据的相关技术,首先先要把虚拟机搞起来,搞起虚拟机第一步先安装系统,接着配置网络 vmware为我们提供了三种网络工作模式,它们分别是:Bridged(桥接模式).N ...
- axios拦截器的介绍
interceptors 拦截器 拦截器一般做什么? 1. 修改请求头的一些配置项 2. 给请求的过程添加一些请求的图标 3. 给请求添加参数 拦截器的基本语法: 拦截器分为全局拦截器和局部拦截器 全 ...
- Rikka with Graph hdu 6090
题解:考虑贪心地一条一条边添加进去. 当 m \leq n-1m≤n−1 时,我们需要最小化距离为 nn 的点对数,所以肯定是连出一个大小为 m+1m+1 的联通块,剩下的点都是孤立点.在这个联通块中 ...
- Css解决表格超出部分用省略号显示
小伙伴们有没有的遇到页面显示时,因为数据太长导致显示的表格某一列过长,从而导致页面的不美观,下面我们来看一看如何用Css样式解决表格超出部分用省略号显示的问题. 主要设置两个样式: table{ ta ...