二叉树 Java 实现 前序遍历 中序遍历 后序遍历 层级遍历 获取叶节点 宽度 ,高度,队列实现二叉树遍历 求二叉树的最大距离
数据结构中一直对二叉树不是很了解,今天趁着这个时间整理一下
许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。
二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的、分别称作这个根的左子树和右子树的二叉树组成。
这个定义是递归的。由于左、右子树也是二叉树, 因此子树也可为空树。下图中展现了五种不同基本形态的二叉树。
其中 (a) 为空树, (b) 为仅有一个结点的二叉树, (c) 是仅有左子树而右子树为空的二叉树, (d) 是仅有右子树而左子树为空的二叉树, (e) 是左、右子树均非空的二叉树。这里应特别注意的是,二叉树的左子树和右子树是严格区分并且不能随意颠倒的,图 (c) 与图 (d) 就是两棵不同的二叉树。
二叉树的遍历
对于二叉树来讲最主要、最基本的运算是遍历。
遍历二叉树 是指以一定的次序访问二叉树中的每个结点。所谓 访问结点 是指对结点进行各种操作的简称。例如,查询结点数据域的内容,或输出它的值,或找出结点位置,或是执行对结点的其他操作。遍历二叉树的过程实质是把二叉树的结点进行线性排列的过程。假设遍历二叉树时访问结点的操作就是输出结点数据域的值,那么遍历的结果得到一个线性序列。
从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
(1)访问结点本身(N),
(2)遍历该结点的左子树(L),
(3)遍历该结点的右子树(R)。
以上三种操作有六种执行次序:
NLR、LNR、LRN、NRL、RNL、RLN。
注意:
前三种次序与后三种次序对称,故只讨论先左后右的前三种次序。
由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtlee)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。
二叉树的java实现
首先创建一棵二叉树如下图,然后对这颗二叉树进行遍历操作(遍历操作的实现分为递归实现和非递归实现),同时还提供一些方法如获取双亲结点、获取左孩子、右孩子等。
特点:
(1) 每个结点最多有两棵子树,没有子树或者只有一棵子树也是可以的;
(2)左子树和右子树是有顺序的,次序不能任意颠倒;
(3)即使树中只有一棵子树,也要区分它是左子树还是右子树;
(2)满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树;如图:
(3)完全二叉树:对一棵具有n个结点的二叉树按层序编号,如果编号为i的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,那么这棵二叉树称为完全二叉树;或者这样理解:在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是右边缺少连续若干个结点,则称此树为完全二叉树;
所以我们可以这样判断完全二叉树:那就是看着树的示意图,心中默默给每个结点按照满二叉树的结构逐层顺序编号,如果编号出现空档,就说明不是完全二叉树,否则就是;
还有个经典问题:
问题一、求二叉树的最大距离;
写一个程序求一棵二叉树相距最远的两个节点之间的距离
如下图:
2.分析与解法
对于任意一个节点,以该节点为根,假设这个根有k个孩子节点,那么距离最远的两个节点U与V之间的路径与这个根节点的关系有两种。
1).若路径经过Root,则U和V属于不同子树的,且它们都是该子树中到根节点最远的节点,否则跟它们的距离最远相矛盾
2).如果路径不经过Root,那么它们一定属于根的k个子树之一,并且它们也是该子树中相距最远的两个顶点
因此,问题就可以转化为在字数上的解,从而能够利用动态规划来解决。
设第K棵子树中相距最远的两个节点:Uk和Vk,其距离定义为d(Uk,Vk),那么节点Uk或Vk即为子树K到根节点Rk距离最长的节点。不失一般性,我们设Uk为子树K中道根节点Rk距离最长的节点,其到根节点的距离定义为d(Uk,R)。取d(Ui,R)(1<=i<=k)中最大的两个值max1和max2,那么经过根节点R的最长路径为max1+max2+2,所以树R中相距最远的两个点的距离为:max{d(U1,V1),…, d(Uk,Vk),max1+max2+2}。
问题二、二叉树宽度
使用队列,层次遍历二叉树。在上一层遍历完成后,下一层的所有节点已经放到队列中,此时队列中的元素个数就是下一层的宽度。以此类推,依次遍历下一层即可求出二叉树的最大宽度。
关于二叉树的介绍如上所示,现在需要自己写一下二叉树的实现,包含了 前序遍历,中序遍历,后序遍历,层级遍历,
以及求二叉树的最大距离,获取二叉树的宽度
- package com.binary_tree;
- import java.util.LinkedList;
- import java.util.Queue;
- public class BinTreeTest1 {
- //地址:
- //https://zhidao.baidu.com/question/441846714.html
- public final static int MAX=40;
- BinTreeTest1[] elements =new BinTreeTest1[MAX];//层次遍历时,保存各个节点;
- int front;//层次遍历时,对首
- int rear;//层次遍历时,对尾
- private Object data;//数据元数
- private BinTreeTest1 left,right;
- private int nMaxLeft;//左子树的最长距离
- private int nMaxRight;//右子数的最长距离;
- private int nMaxLen; //最长距离
- private int treeWidth;//二叉树宽度
- public BinTreeTest1(){}
- public BinTreeTest1(Object data){
- this.data=data;
- left=null;
- right=null;
- }
- public BinTreeTest1(Object data,BinTreeTest1 left,BinTreeTest1 right){
- this.data=data;
- this.left=left;
- this.right=right;
- }
- public String toString(){
- return data.toString();
- }
- //层次遍历二叉树 ,并获取二叉树的宽度
- //参考:http://www.cnblogs.com/xudong-bupt/p/4036190.html
- public void LayerOrder(BinTreeTest1 root){
- //http://www.cnblogs.com/beihoushan/p/6401416.html
- if(root==null) return;
- Queue<BinTreeTest1> queue=new LinkedList<BinTreeTest1>();
- queue.add(root);
- while(queue.size()!=0){
- int len = queue.size();
- treeWidth=Math.max(treeWidth,len);
- System.out.println("层级遍历="+len);
- for(int i=0;i<len;i++){
- BinTreeTest1 temp=queue.poll();
- System.out.println("层级遍历111="+queue.size());
- System.out.println(temp.data);
- if(temp.left!=null) queue.add(temp.left);
- if(temp.right!=null) queue.add(temp.right);
- System.out.println("层级遍历111="+queue.size());
- }
- }
- }
- //前序遍历
- public static void preOrder(BinTreeTest1 parent){
- if(parent==null) return;
- System.out.println(parent.data+" ");
- preOrder(parent.left);
- preOrder(parent.right);
- }
- //中序遍历
- public static void inOrder(BinTreeTest1 parent){
- if(parent==null) return;
- inOrder(parent.left);
- System.out.println(parent.data+" ");
- inOrder(parent.right);
- }
- //后序遍历
- public static void postOrder(BinTreeTest1 parent){
- if(parent==null) return;
- postOrder(parent.left);
- postOrder(parent.right);
- System.out.println(parent.data+" ");
- }
- //返回树的叶子节点数
- public int leaves(){
- if(this==null) return 0;
- if(left==null&&right==null) {
- System.out.print(this.data);
- return 1;
- }
- //左边节点数
- int leftCount=(left==null?0:left.leaves());
- int rightCount=(right==null?0:right.leaves());
- return leftCount+rightCount;
- }
- //返回树的叶子节点数
- public int Allleaves(){
- if(this==null) return 0;
- System.out.print(this.data);
- if(left==null&&right==null) {
- return 1;
- }
- //左边节点数
- int leftCount=(left==null?0:left.Allleaves());
- int rightCount=(right==null?0:right.Allleaves());
- return 1+leftCount+rightCount;
- }
- // 获取高度
- public int height(){
- int heightOfTree;
- if(this==null) return 0;
- int leftHeight=(left==null?0:left.height());
- int rightHeight=(right==null?0:right.height());
heightOfTree=Math.max(leftHeight,rightHeight);- System.out.println("value=="+this.data+" left right=="+leftHeight+" right height=="+rightHeight);
- return 1+heightOfTree;
- }
- public void getMaxDistance(BinTreeTest1 parent) {
- // TODO Auto-generated method stub
- if(parent==null) return; //叶子节点 返回
- if(parent.left==null) parent.nMaxLeft=0;
- if(parent.right==null) parent.nMaxRight=0;
- if(parent.left!=null) getMaxDistance(parent.left); //如果左子树不为空,递归寻找左子树最长距离
- if(parent.right!=null) getMaxDistance(parent.right);//如果右子树不为空,递归寻找右子树最长距离
- if(parent.left!=null){
- parent.nMaxLeft=Math.max(parent.left.nMaxLeft, parent.left.nMaxRight) +1;
- }
- if(parent.right!=null){
- parent.nMaxRight=Math.max(parent.right.nMaxLeft, parent.right.nMaxRight) +1;
- }
- nMaxLen=Math.max(parent.nMaxLeft+parent.nMaxRight,nMaxLen);
- }
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- BinTreeTest1 e=new BinTreeTest1("E");
- BinTreeTest1 g=new BinTreeTest1("G");
- BinTreeTest1 h=new BinTreeTest1("H");
- BinTreeTest1 i=new BinTreeTest1("I");
- BinTreeTest1 d=new BinTreeTest1("D",null,g);
- BinTreeTest1 f=new BinTreeTest1("F",h,i);
- BinTreeTest1 b=new BinTreeTest1("B",d,e);
- BinTreeTest1 c=new BinTreeTest1("C",f,null);
- BinTreeTest1 tree=new BinTreeTest1("A",b,c);
- System.out.println("前序遍历二叉树结果:\n");
- tree.preOrder(tree);
- System.out.println("中序遍历二叉树结果:\n");
- tree.inOrder(tree);
- System.out.println("后序遍历二叉树结果:\n");
- tree.postOrder(tree);
- System.out.println("层级遍历二叉树:\n");
- tree.LayerOrder(tree);
- System.out.println("二叉树的宽度:"+tree.treeWidth);
- System.out.println("二叉树的高度:"+tree.height());
- System.out.println();
- System.out.println("二叉树的节点数为;"+tree.leaves());
- System.out.println("二叉树的所有的节点数为:"+tree.Allleaves());
- System.out.println("获取二叉树的最大距离:\n");
- tree.getMaxDistance(tree);
- System.out.println("MaxLen="+tree.nMaxLen);
- }
- }
以上包含了全部的遍历方式,其中层级遍历使用了队列,简明扼要,关于队列的知识,如果需要了解的很详细可以参考下一篇博文
二叉树 Java 实现 前序遍历 中序遍历 后序遍历 层级遍历 获取叶节点 宽度 ,高度,队列实现二叉树遍历 求二叉树的最大距离的更多相关文章
- Java实现二叉树的前序、中序、后序遍历(非递归方法)
在上一篇博客中,实现了Java中二叉树的三种遍历方式的递归实现,接下来,在此实现Java中非递归实现二叉树的前序.中序.后序遍历,在非递归实现中,借助了栈来帮助实现遍历.前序和中序比较类似,也简单 ...
- Java实现二叉树的前序、中序、后序、层序遍历(非递归方法)
在上一篇博客中,实现了Java中二叉树的四种遍历方式的递归实现,接下来,在此实现Java中非递归实现二叉树的前序.中序.后序.层序遍历,在非递归实现中,借助了栈来帮助实现遍历.前序和中序比较类似, ...
- LeetCode二叉树的前序、中序、后序遍历(递归实现)
本文用递归算法实现二叉树的前序.中序和后序遍历,提供Java版的基本模板,在模板上稍作修改,即可解决LeetCode144. Binary Tree Preorder Traversal(二叉树前序遍 ...
- Java实现二叉树的先序、中序、后序、层序遍历(递归和非递归)
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易 ...
- JAVA下实现二叉树的先序、中序、后序、层序遍历(递归和循环)
import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Queue; ...
- 【2】【leetcode-105,106】 从前序与中序遍历序列构造二叉树,从中序与后序遍历序列构造二叉树
105. 从前序与中序遍历序列构造二叉树 (没思路,典型记住思路好做) 根据一棵树的前序遍历与中序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [ ...
- PHP递归方法实现前序、中序、后序遍历二叉树
二叉树是每个节点最多有两个子树的树结构.通常子树被称作“左子树”(left subtree)和“右子树”(right subtree). class Node { public $value; pub ...
- Java实现二叉树先序,中序,后序,层次遍历
一.以下是我要解析的一个二叉树的模型形状.本文实现了以下方式的遍历: 1.用递归的方法实现了前序.中序.后序的遍历: 2.利用队列的方法实现层次遍历: 3.用堆栈的方法实现前序.中序.后序的遍历. . ...
- 二叉树各种相关操作(建立二叉树、前序、中序、后序、求二叉树的深度、查找二叉树节点,层次遍历二叉树等)(C语言版)
将二叉树相关的操作集中在一个实例里,有助于理解有关二叉树的相关操作: 1.定义树的结构体: typedef struct TreeNode{ int data; struct TreeNode *le ...
随机推荐
- Spring学习(十四)----- Spring Auto Scanning Components —— 自动扫描组件
一. Spring Auto Scanning Components —— 自动扫描组件 1. Declares Components Manually——手动配置componen ...
- BLACKPYTHON学习(一)
C/S结构了解 所谓的C/S就是客户端(client)和服务器端(server)的简称,也就是在基于这个的基础上编写相关的代码:一个就是客户端一个就是服务端. TCP(client) 客户端编写 #因 ...
- Java中 static、final和static final的特点及区别
final: final可以修饰:属性,方法,类,局部变量(方法中的变量) final修饰的属性的初始化可以在编译期,也可以在运行时,初始化后不能被改变. final修饰的属性跟具体对象有关,在运行期 ...
- 基于WebSocket协议的性能测试
互联网应用时代,用户获取信息的方式从传统媒体到新媒体,信息时效性对通信技术要求越来越高, HTTP协议已经不能适用.于是WebSocket出现了,它实现浏览器与服务器的全双工通信,服务端主动向客户端发 ...
- Windows10子系统安装ubuntu+kali渗透环境
Windows10安装子系统ubuntu,安装完ubuntu后再安装katoolin才能使用kali. (katoolin渗透测试的Linux发行版,它可以让你在其他Linux发行版上使用Kali的全 ...
- js中 null, undefined, 0,空字符串,false,不全等比较
null == undefined // true null == '' // false null == 0 // false null == false // false undefined = ...
- java分布式事务,及解决方案
1.什么是分布式事务 分布式事务就是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上.以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成 ...
- Django_csrf
CSRF攻击介绍 CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作.比如说,受害者 Bob 在银行有一笔存款,通过对银行的 ...
- 通过NPM快速发布你的NodeJS模块(组件包)
1.更新 NPM - [ npm install -g npm | 该步骤可选:最好使用新版本] 楼主当前版本号 2.6.1 ,如果更新报错,可以尝试 国内淘宝镜像 $ npm -v 2.6.1 // ...
- 第26次Scrum会议(11/14)【欢迎来怼】
一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/11/14 11:35~11:57,总计22min.地点:东北 ...