(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)的更多相关文章

  1. 毕业了-java二叉树层次遍历算法

    /*************************************** * 时间:2017年6月23日 * author:lcy * 内容:二叉树的层次遍历 * 需要借助队列这个数据结构,直 ...

  2. java 二叉树递归遍历算法

    //递归中序遍历 public void inorder() { System.out.print("binaryTree递归中序遍历:"); inorderTraverseRec ...

  3. java树的遍历

    java二叉树的遍历算法: http://blog.sina.com.cn/s/blog_70600f720100ujnp.html

  4. 【Java】 二叉树的遍历(递归与循环+层序遍历)

    在[Java] 大话数据结构(9) 树(二叉树.线索二叉树)一文中,已经实现了采用递归方法的前.中.后序遍历,本文补充了采用循环的实现方法.以及层序遍历并进行了一个总结. 递归实现 /* * 前序遍历 ...

  5. 二叉树 Java 实现 前序遍历 中序遍历 后序遍历 层级遍历 获取叶节点 宽度 ,高度,队列实现二叉树遍历 求二叉树的最大距离

    数据结构中一直对二叉树不是很了解,今天趁着这个时间整理一下 许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显 ...

  6. 【LeetCode-面试算法经典-Java实现】【107-Binary Tree Level Order Traversal II(二叉树层序遍历II)】

    [107-Binary Tree Level Order Traversal II(二叉树层序遍历II)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a ...

  7. 数据结构Java版之遍历二叉树(六)

    二叉树是我们在程序中用的最多的一种树(个人观点).最简单的一个二叉树是由一个根节点,两个子节点(一左一右成左右孩子节点)组成.二叉树是数组和链表的结合,即包含了数组的快速查找优点,又包含了链表的快速添 ...

  8. Java数据结构——二叉树的遍历(汇总)

    二叉树的遍历分为深度优先遍历(DFS)和广度优先遍历(BFS) DFS遍历主要有: 前序遍历 中序遍历 后序遍历 一.递归实现DFSNode.java: public class Node { pri ...

  9. Java 二叉树遍历右视图-LeetCode199

    题目如下: 题目给出的例子不太好,容易让人误解成不断顺着右节点访问就好了,但是题目意思并不是这样. 换成通俗的意思:按层遍历二叉树,输出每层的最右端结点. 这就明白时一道二叉树层序遍历的问题,用一个队 ...

随机推荐

  1. PDF 文件编写器 C# 类库(版本 1.28.0)使用详解

    PDF File Writer 是一个 C# .NET 类库,允许应用程序创建 PDF 文件. PDF File Writer C# 类库使 .NET 应用程序能够生成 PDF 文档.该库使应用程序免 ...

  2. Docker学习(13) Docker容器的网络连接

    Docker容器的网络连接 Docker容器的网络基础 先安装网桥管理工具 Docker容器的互联 默认 Docker容器与外部网络的连接

  3. Mobileye高级驾驶辅助系统(ADAS)

    Mobileye高级驾驶辅助系统(ADAS) Mobileye is the global leader in the development of vision technology for Adv ...

  4. TensorFlow分布式详解

    每次 TensorFlow 运算都被描述成计算图的形式,允许结构和运算操作配置所具备的自由度能够被分配到各个分布式节点上.计算图可以分成多个子图,分配给服务器集群中的不同节点. 强烈推荐读者阅读论文& ...

  5. 旷视MegEngine网络搭建

    旷视MegEngine网络搭建 在 基本概念 中,介绍了计算图.张量和算子,神经网络可以看成一个计算图.在 MegEngine 中,按照计算图的拓扑结构,将张量和算子连接起来,即可完成对网络的搭建.M ...

  6. MinkowskiEngine Miscellaneous Classes杂类

    Miscellaneous Classes杂类 内核生成器 class MinkowskiEngine.KernelGenerator(kernel_size = -1,stride = 1,dila ...

  7. jmeter工作目录介绍、jmeter元件及组件介绍

    一.jmeter工作目录介绍: bin:放置各项配置文件(如日志设置.JVM设置).启动文件.启动Jar包.示例脚本等: docs:放置JMeter API的离线帮助文档: extras:JMeter ...

  8. Lombok——一款Java构建工具,“懒人”必备!!(idea版)

    一.简介 Lombok 是一种 Jav 构建工具,可用来帮助开发人员消除 Java 的冗长代码,尤其是对于简单的 Java 对象(POJO).它是通过注解实现这一目的. 二.使用 1.在idea中安装 ...

  9. vue3.0的变化

    初涉vue3.0,下面是我在demo中遇到的一些问题(我是用的vue-cli进行开发) [1]main.js中配置  第一个变化 vue2.x ===  Vue.prototype.$baseURL= ...

  10. 一篇文章带你吃透,Java界最神秘技术ClassLoader

    ClassLoader 是 Java 届最为神秘的技术之一,无数人被它伤透了脑筋,摸不清门道究竟在哪里.网上的文章也是一篇又一篇,经过本人的亲自鉴定,绝大部分内容都是在误导别人.本文我带读者彻底吃透 ...