java二叉树的遍历(1)
树(tree)是一种抽象数据类型(ADT),用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合
节点:上图的圆圈,比如A,B,C等都是表示节点。节点一般代表一些实体,在java面向对象编程中,节点一般代表对象。
边:连接节点的线称为边,边表示节点的关联关系。一般从一个节点到另一个节点的唯一方法就是沿着一条顺着有边的道路前进。在Java当中通常表示引用。
每个节点最多只能有两个子节点的一种形式称为二叉树
一、树的基本概念
路径:顺着节点的边从一个节点走到另一个节点,所经过的节点的顺序排列就称为“路径”。
根:树顶端的节点称为根。一棵树只有一个根,如果要把一个节点和边的集合称为树,那么从根到其他任何一个节点都必须有且只有一条路径。A是根节点。
父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;B是D的父节点。
子节点:一个节点含有的子树的根节点称为该节点的子节点;D是B的子节点。
兄弟节点:具有相同父节点的节点互称为兄弟节点;比如上图的D和E就互称为兄弟节点。
叶节点:没有子节点的节点称为叶节点,也叫叶子节点,比如上图的H、E、F、G都是叶子节点。
子树:每个节点都可以作为子树的根,它和它所有的子节点、子节点的子节点等都包含在子树中。
节点的层次:从根开始定义,根为第一层,根的子节点为第二层,以此类推。
深度:对于任意节点n,n的深度为从根到n的唯一路径长,根的深度为0;
高度:对于任意节点n,n的高度为从n到一片树叶的最长路径长,所有树叶的高度为0,即最大层数
二、二叉树的遍历
二叉树:每个节点最多只有两个子节点的树
如果二叉树的所有叶子节点都在最后一层,并且节点总数= 2^n -1,n 为层数,则该树为满二叉树
如果二叉树的所有叶子节点都在最后一层或倒数第二层,并且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,则称为完全二叉树
- 二叉树的遍历方式有三种:
前序遍历: 根,左,右
中序遍历: 左,根,右
后序遍历:左,右,根
- 二叉树的建立和添加 ,这里以二叉排序数为例
public class TreeNodeTest {
public static void main(String[] args) {
int[] arr={5,4,7,9,2,6,3};
TreeNode tree = new TreeNode();
for (int i=0;i<arr.length;i++){
tree.add(new Node(arr[i]));
}
}
}
class TreeNode{
Node root;//根节点
public TreeNode() {
}
public void add(Node node){
if (node==null) return;
if (root==null) {root=node;return;}
else root.add(node);
} public void prefix() {
if (root==null) return;
else root.prefix();
}
}
class Node{
int val; //节点值
Node left;// 左节点
Node right; // 右节点 public Node(int val) {
this.val = val;
} public void add(Node node) {
if (node==null)return;
if (node.val<val) {
if (left==null){left=node;return;}
else left.add(node);}
else {
if(right==null) {right=node;return;}
else right.add(node);
}
}
}
三、递归前、中、后序遍历
- 前序遍历递归步骤:先输出当前节点,如果左子树不为空,向左递归;如果右子树不为空,向右递归
- 中序遍历递归步骤:如果左子树不为空,向左递归;输出当前节点;如果右子树不为空,向右递归
- 后序遍历递归步骤:如果左子树不为空,向左递归;如果右子树不为空,向右递归;输出当前节点
//TreeNode类下
//前序递归遍历
public void preOrder() {
if (this.root!=null) this.root.preOrder();
else System.out.println("根节点为空");
}
//中序递归遍历
public void infixOrder() {
if (this.root!=null) this.root.infixOrder();
else System.out.println("根节点为空");
}
//后序递归遍历
public void postOrder() {
if (this.root!=null) this.root.postOrder();
else System.out.println("根节点为空");
}
//Node类下 //前序递归遍历
public void preOrder() {
System.out.print(this.val+ " ");
if (this.left!=null) this.left.preOrder();
if (this.right!=null)this.right.preOrder(); }
//中序递归遍历
public void infixOrder() {
if (this.left!=null) this.left.infixOrder();
System.out.print(this.val+ " ");
if (this.right!=null)this.right.infixOrder();
}
//后序递归遍历
public void postOrder() {
if (this.left!=null) this.left.postOrder();
if (this.right!=null)this.right.postOrder();
System.out.print(this.val+ " ");
}
四、非递归前中后序遍历
- 前序遍历思路:利用一个栈来实现先序遍历
- 根节点入栈
- 判断栈是否为空,如果不为空,弹出栈顶元素并打印
- 如果有右子树,压栈
- 如果有左子树,压栈
- 如果栈为空,程序结束
public void prefix() {
Stack<Node> s= new Stack<>();
s.push(this);
while (!s.isEmpty()){
Node node = s.pop();
System.out.print(node.val+"-->");
if(node.right!=null) s.push(node.right);
if(node.left!=null) s.push(node.left);
}
}
- 中序遍历思路:利用一个栈来实现先序遍历,左根右
根节点入栈
如果节点不为空,压栈,沿着左子树走一步
如果节点为空,则出栈,打印,沿着右子树走一步
如果栈为空且当前节点为空,则结束
//中序遍历
public void infixOrder() {
//非递归
Stack<Node> s=new Stack<>();
Node node= this;
while (!s.isEmpty()||node!=null){
if (node!=null){
s.push(node);
node=node.left;
}
else {
node=s.pop();
System.out.print(node.val+ " ");
node=node.right;
}
}
}
- 后序遍历思路:利用2个栈来实现后序遍历
申请两个栈s1,s2,头节点入栈s1
如果栈s1不为空,执行以下操作:弹出一个元素,入栈s2,
如果该节点左孩子不空,入栈s1,如果该节点右孩子不空入栈s1
将栈s2中的节点一次出栈,打印
public void postOrder() {
//非递归
Stack<Node> s1=new Stack<>();
Stack<Node> s2=new Stack<>();
s1.push(this);
while(!s1.isEmpty()){
Node node = s1.pop();
s2.push(node);
if (node.left!=null) s1.push(node.left);
if (node.right!=null) s1.push(node.right);
}
while (!s2.isEmpty())
System.out.print(s2.pop().val+ " "); // 一种栈实现
/*
Stack<Node> s=new Stack<>();
Node node= this;
Node lastnode= null;
while (node!=null){
s.push(node); //将所有左节点入栈
node=node.left;
}
while(!s.isEmpty()){
node=s.pop();
//一个根节点被访问的前提是:无右子树或右子树已被访问过
if (node.right!=null&&node.right!=lastnode){
s.push(node);
node=node.right;
while (node!=null)
{ s.push(node);
node=node.left;}
} else {
System.out.print(node.val+ " ");
lastnode=node;
}
}
*/
}
五、前中序查找
- 前序查找:
- 先判断当前节点值是否为查找值,如果是返回当前节点
- 判断当前节点的左子节点是否为空,如果不为空,左子树递归前序查找
- 如果左递归返回的值不为空,说明找到,返回该节点
- 否则判断当前节点是否有右子节点,如果有,右子树递归前序查找
- 中序查找:
- 判断当前节点的左子节点是否为空,如果不为空,左子树递归中序查找
- 如果左递归返回的值不为空,说明找到,返回该节点
- 否则判断当前节点值是否为查找值,如果是返回当前节点
- 否则判断当前节点是否有右子节点,如果有,右子树递归中序查找
- 后序递归查找
- 判断当前节点的左子节点是否为空,如果不为空,左子树递归后序查找
- 如果左递归返回的值不为空,说明找到,返回该节点
- 否则判断当前节点是否有右子节点,如果有,右子树递归后序查找
- 如果右递归返回的值不为空,说明找到,返回该节点
- 否则判断当前节点值是否为查找值,如果是返回当前节点
//前序递归查找
public TreeNode preOrderSearch(int val) {
System.out.println("前序递归查找");
if(this.val==val) {return this;}
TreeNode node = null;
if (this.left!=null){node=this.left.preOrderSearch(val);}
if (node!=null) return node;
//1.左递归前序查找,找到结点,则返回,否继续判断,
//2.当前的结点的右子节点是否为空,如果不空,则继续向右递归前序查找
if (this.right!=null){node=this.right.preOrderSearch(val);}
return node; }
//中序递归查找
public TreeNode infixOrderSearch(int val) {
TreeNode node = null;
//1.左递归前序查找,找到结点,则返回,否继续判断,
if (this.left!=null){node=this.left.infixOrderSearch(val);}
if (node!=null) return node;
System.out.println("中序递归查找");
if(this.val==val) {return this;}
//2.当前的结点的右子节点是否为空,如果不空,则继续向右递归前序查找
if (this.right!=null){node=this.right.infixOrderSearch(val);}
return node;
}
//后序递归查找
public TreeNode postOrderSearch(int val) {
TreeNode node = null;
//1.左递归前序查找,找到结点,则返回,否继续判断,
if (this.left!=null){node=this.left.postOrderSearch(val);}
if (node!=null) return node;
if (this.right!=null){node=this.right.postOrderSearch(val);}
if (node!=null) return node;
System.out.println("后序递归查找");
if(this.val==val) {return this;}
return node;
}
java二叉树的遍历(1)的更多相关文章
- 毕业了-java二叉树层次遍历算法
/*************************************** * 时间:2017年6月23日 * author:lcy * 内容:二叉树的层次遍历 * 需要借助队列这个数据结构,直 ...
- java 二叉树递归遍历算法
//递归中序遍历 public void inorder() { System.out.print("binaryTree递归中序遍历:"); inorderTraverseRec ...
- java树的遍历
java二叉树的遍历算法: http://blog.sina.com.cn/s/blog_70600f720100ujnp.html
- 【Java】 二叉树的遍历(递归与循环+层序遍历)
在[Java] 大话数据结构(9) 树(二叉树.线索二叉树)一文中,已经实现了采用递归方法的前.中.后序遍历,本文补充了采用循环的实现方法.以及层序遍历并进行了一个总结. 递归实现 /* * 前序遍历 ...
- 二叉树 Java 实现 前序遍历 中序遍历 后序遍历 层级遍历 获取叶节点 宽度 ,高度,队列实现二叉树遍历 求二叉树的最大距离
数据结构中一直对二叉树不是很了解,今天趁着这个时间整理一下 许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显 ...
- 【LeetCode-面试算法经典-Java实现】【107-Binary Tree Level Order Traversal II(二叉树层序遍历II)】
[107-Binary Tree Level Order Traversal II(二叉树层序遍历II)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a ...
- 数据结构Java版之遍历二叉树(六)
二叉树是我们在程序中用的最多的一种树(个人观点).最简单的一个二叉树是由一个根节点,两个子节点(一左一右成左右孩子节点)组成.二叉树是数组和链表的结合,即包含了数组的快速查找优点,又包含了链表的快速添 ...
- Java数据结构——二叉树的遍历(汇总)
二叉树的遍历分为深度优先遍历(DFS)和广度优先遍历(BFS) DFS遍历主要有: 前序遍历 中序遍历 后序遍历 一.递归实现DFSNode.java: public class Node { pri ...
- Java 二叉树遍历右视图-LeetCode199
题目如下: 题目给出的例子不太好,容易让人误解成不断顺着右节点访问就好了,但是题目意思并不是这样. 换成通俗的意思:按层遍历二叉树,输出每层的最右端结点. 这就明白时一道二叉树层序遍历的问题,用一个队 ...
随机推荐
- 学习Git的一些总结
Git是以后公司工作必不可少的,所以早点了解使用它是很有必要的 一般国外的开源是GitHub 国内的是码云Gitee 至于git的安装教程,这里就不啰嗦啦,面向百度即可,安装完成鼠标右键会多几个选项: ...
- 激光SLAM与视觉SLAM的特点
激光SLAM与视觉SLAM的特点 目前,SLAM技术被广泛运用于机器人.无人机.无人驾驶.AR.VR等领域,依靠传感器可实现机器的自主定位.建图.路径规划等功能.由于传感器不同,SLAM的实现方式也有 ...
- MinkowskiNonlinearities非线性
MinkowskiNonlinearities非线性 MinkowskiReLU class MinkowskiEngine.MinkowskiReLU(*args, **kwargs) __init ...
- Pass Infrastructure基础架构(上)
Pass Infrastructure基础架构(上) Operation Pass OperationPass : Op-Specific OperationPass : Op-Agnostic De ...
- python路径写入注册表,导入三方模块win32
python在安装第三方模块时候,需要将python的路径写入注册表,否则会提示 'python version 3.8-32 required,which was not found in the ...
- P5960 【模板】差分约束算法
题目描述 给出一组包含 $m$ 个不等式,有 $n$ 个未知数的形如: 的不等式组,求任意一组满足这个不等式组的解. 输入格式 第一行为两个正整数 $n,m$,代表未知数的数量和不等式的数量. 接下来 ...
- 阅读源码很重要,以logback为例,分享一个小白都能学会的读源码方法
作为一个程序员,经常需要读一些开源项目的源码.同时呢,读源码对我们也有很多好处: 1.提升自己 阅读优秀的代码,第一可以提升我们自身的编码水平,第二可以开拓我们写代码的思路,第三还可能让我们拿到大厂 ...
- 【Android编程】Java利用Socket类编写Metasploit安卓载荷辅助模块
/作者:Kali_MG1937 CSDN博客:ALDYS4 QQ:3496925334/ 注意!此文章被作者标记到 黑历史 专栏中,这意味着本篇文章可能存在 质量低下,流水账文,笔法低质 的问题 为了 ...
- 【题解】数颜色 STL vector数组
小 C 的兔子不是雪白的,而是五彩缤纷的. 题目 题目描述 小 C 的兔子不是雪白的,而是五彩缤纷的.每只兔子都有一种颜色,不同的兔子可能有 相同的颜色.小 C 把她标号从 1 到 n 的 n只兔子排 ...
- VBS脚本编程(5)——过程与函数
过程是构成程序的一个模块,往往用来完成一个相对独立的功能.过程可以使程序更清. Sub过程与Function函数的区别: Sub没有返回值,Function有返回值: Sub不能放在表达式中,Func ...