树节点定义:

class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}

递归建立二叉树:

    //递归建立二叉树
public static void BuildTree(TreeNode node, int data){
if(node == null){
node = new TreeNode(data);
} if(data <= node.val){
if(node.left == null){
node.left = new TreeNode(data);
}else{
BuildTree(node.left, data);
}
} if(data > node.val){
if(node.right == null){
node.right = new TreeNode(data);
}else{
BuildTree(node.right, data);
}
}
}

1、先序遍历

遍历方式:根节点-->左节点-->右节点

递归先序遍历:

    //先序递归遍历二叉树
public static List<Integer> preTravese(TreeNode root,List<Integer> arr){
if(root == null)
return arr;
if(root != null){
arr.add(root.val);
arr = preTravese(root.left,arr);
arr = preTravese(root.right,arr);
}
return arr;
}

非递归遍历:

对于任意一个结点p

1)访问结点p,并将p入栈

2)将p变为p的左孩子结点,如果p的不为空,循环至 1); 否则弹出当前栈顶使用p接收,将p变为p的右孩子结点;

3)当p结点为null并且栈为空时,结束循环。

代码:

    //非递归先序遍历
public static List<Integer> preorderTraversal(TreeNode root){
List<Integer> arr = new ArrayList<Integer>();
if(root == null){
return arr;
}
Stack<TreeNode> ts = new Stack<TreeNode>();
TreeNode ptr = root;
while( ptr != null || !ts.isEmpty()){
while(ptr != null){
arr.add(ptr.val);
ts.push(ptr);
ptr = ptr.left;
}
if( !ts.isEmpty()){
ptr = ts.pop();
ptr = ptr.right;
}
}
return arr;
}

2、中序遍历

遍历方式: 左子树-->根节点-->右子树

递归中序遍历:

    //中序递归遍历二叉树
public static List<Integer> inTravese(TreeNode root,List<Integer> arr){
if(root == null)
return arr;
if(root != null){
arr = inTravese(root.left,arr);
arr.add(root.val);
arr = inTravese(root.right,arr);
}
return arr;
}

非递归中序遍历:

对于任意一个结点p

1)当结点不为null,将结点压栈;

2)将p更新为它的左孩子,如果左孩子不为空,循环至 1);否则弹出栈顶元素赋值给p,访问p结点,p更新为p的右孩子;

3)当p为null 并且栈为空时结束循环。

代码:

    //中序非递归遍历
public static List<Integer> inorderTraversal(TreeNode root){
List<Integer> arr = new ArrayList<Integer>();
if(root == null){
return arr;
}
Stack<TreeNode> ts = new Stack<TreeNode>();
TreeNode ptr = root;
while( ptr != null || !ts.isEmpty() ){
while(ptr != null){
ts.push(ptr);
ptr = ptr.left;
}
if(!ts.isEmpty()){
ptr = ts.pop();
arr.add(ptr.val);
ptr = ptr.right;
}
}
return arr;
}

3、后序遍历

遍历方式:左子树-->右子树-->根节点

递归遍历:

    //后序递归遍历二叉树
public static List<Integer> lastTravese(TreeNode root,List<Integer> arr){
if(root == null)
return arr;
if(root != null){
arr = lastTravese(root.left,arr);
arr = lastTravese(root.right,arr);
arr.add(root.val);
}
return arr;
}

非递归遍历:

对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因为其右孩子还没有被访问。

接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。

这样就可以保证正确的访问顺序。

可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。

代码:

首先新建一个类来记录结点是否是第一次弹栈:

//新建一个类,用来记录该结点是不是第一次弹栈
class NewTreeNode{
TreeNode ptr;
boolean isFirst;
public NewTreeNode(TreeNode ptr){
this.ptr = ptr;
this.isFirst = true;
}
}

非递归后序遍历二叉树:

    //后序非递归遍历二叉树
public static List<Integer> lastTraverse(TreeNode root){
List<Integer> arr = new ArrayList<Integer>();
if(root == null){
return arr;
}
Stack<NewTreeNode> nts = new Stack<NewTreeNode>();
NewTreeNode nptr = null;
TreeNode ptr = root;
while( ptr!= null || !nts.isEmpty()){
while(ptr != null){
nptr = new NewTreeNode(ptr);
nts.push(nptr);
ptr = ptr.left;
} if(!nts.isEmpty()){
nptr = nts.pop();
if(nptr.isFirst){
nptr.isFirst = false;
nts.push(nptr);
ptr = nptr.ptr.right;
}else{
arr.add(nptr.ptr.val);
//ptr置为null,因为此时它的左右子树都已经访问完毕
ptr = null;
}
}
}
return arr;
} }

二叉树的先序、中序以及后序遍历(递归 && 非递归)的更多相关文章

  1. 递归/非递归----python深度遍历二叉树(前序遍历,中序遍历,后序遍历)

    递归代码:递归实现很简单 '二叉树结点类' class TreeNode: def __init__(self, x): self.val = x self.left = None self.righ ...

  2. 二叉树的递归,非递归遍历(C++)

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

  3. 【数据结构】——搜索二叉树的插入,查找和删除(递归&非递归)

    一.搜索二叉树的插入,查找,删除 简单说说搜索二叉树概念: 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右 ...

  4. c/c++二叉树的创建与遍历(非递归遍历左右中,破坏树结构)

    二叉树的创建与遍历(非递归遍历左右中,破坏树结构) 创建 二叉树的递归3种遍历方式: 1,先中心,再左树,再右树 2,先左树,再中心,再右树 3,先左树,再右树,再中心 二叉树的非递归4种遍历方式: ...

  5. C++二叉树前中后序遍历(递归&非递归)统一代码格式

    统一下二叉树的代码格式,递归和非递归都统一格式,方便记忆管理. 三种递归格式: 前序遍历: void PreOrder(TreeNode* root, vector<int>&pa ...

  6. 已知二叉树的中序序列为DBGEAFC,后序序列为DGEBFCA,给出相应的二叉树

    面对这种问题时我们该怎么解决? 今天写数据结构题.发现了一道总是碰见问题的题在这里我写了一种求解方法我自己称它为分层递归求解. 第一步通过观察我们知道后序遍历时最后一个是根节点A 在中序序列中A的左边 ...

  7. leetcode 236. 二叉树的最近公共祖先LCA(后序遍历,回溯)

    LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百 ...

  8. LeetCode 145 二叉树的后序遍历(非递归)

    题目: 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路: 1 ...

  9. 二叉树——遍历篇(递归/非递归,C++)

    二叉树--遍历篇 二叉树很多算法题都与其遍历相关,笔者经过大量学习.思考,整理总结写下二叉树的遍历篇,涵盖递归和非递归实现. 1.二叉树数据结构及访问函数 #include <stdio.h&g ...

随机推荐

  1. PHP学习(三)----面向对象

    首先,还是建立一个好的理解模型: 1.什么是面向对象? 面向对象分为两个部分,那就是:什么是对象和什么是面向? 什么是对象: 对象的出现就是为了用代码更好的绘制我们现有的世界.那到底什么是对象呢? 一 ...

  2. 前端框架Bootstrap的Modal使用Ajax数据源,如何避免数据被缓存

    1.绑定事件,在关闭的时候,直接将数据清除: $("#model").on("hidden.bs.model",function(e){$(this).remo ...

  3. Error:(12) No resource identifier found for attribute 'titles' in package 'com.itheima52.mobilesafe5

    http://stackoverflow.com/questions/5819369/error-no-resource-identifier-found-for-attribute-adsize-i ...

  4. Medusa: Gauges for JavaFX

    Medusa: Gauges for JavaFX https://community.oracle.com/docs/DOC-992746

  5. C# DateTime类型和时间戳 互相转换

    /// <summary> /// 时间戳转为C#格式时间 /// </summary> /// <param name=”timeStamp”></para ...

  6. 读书笔记——《图解TCP/IP》(1/4)

    读书笔记——<图解TCP/IP>(1/4) 经典摘抄 第一章 网络基础知识 1.独立模式:计算机未连接到网络,各自独立使用的方式. 2.广域网 WAN 局域网 LAN 城域网 MAN 3. ...

  7. WCF TCP 错误代码 10061: 由于目标计算机积极拒绝

    表象是连不上服务端,本质原因多种多样,网络硬件问题导致的网络不通.服务本身问题或没有启动.或者防火墙阻隔等等不一而足. 1.ping看服务端能否ping通: 2.telnet ip地址 端口 ,看看是 ...

  8. HDFS API 文件读写代码演示

    一:准备工作 1.新建class类 2.开启HDFS服务 3.将配置文件拷贝进resources路径 方便了Configuration的读取配置. 二:读出HDFS文件系统中的文件到控制台 4.读出在 ...

  9. Linux环境下配置eclipse,以及创建maven工程

    一:maven的安装 1.安装配置maven环境变量 2.验证 二:eclipse的安装 3.解压配置eclipse 4.启动eclipse,必须在虚拟机的eclipse下启动 5.结果 三:修改配置 ...

  10. 在Android Studio 中正确使用adil ”绝对经典“

    今天调用远程服务中遇到了一个问题,哎,调了2个小时,后来终于解决,总结来看还是对新的Android Studio 不够熟悉.那么....就可以睡觉啦!!! 在Android Studio中使用进程通信 ...