数据结构中一直对二叉树不是很了解,今天趁着这个时间整理一下

许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。
    二叉树(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.htmlpublic  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.htmlpublic void LayerOrder(BinTreeTest1 root){//http://www.cnblogs.com/beihoushan/p/6401416.htmlif(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 stubif(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 Queue 专题

参考:[编程之美]求二叉树中节点的最大距离

参考:求二叉树的深度和宽度[Java]

转载于:https://www.cnblogs.com/aspirant/p/6796329.html

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

  1. java根据前序和中序建树_Java实现根据前序遍历构建二叉树(前序遍历、中序遍历、后序遍历)...

    Java实现根据前序遍历构建二叉树(前序遍历.中序遍历.后序遍历),Java关于ACM的代码真的好少,想参考如何用java实现二叉树googl 前言 Java关于ACM的代码真的好少,想参考如何用ja ...

  2. 二叉树广度优先搜索、深度优先搜索(前序、中序、后序)遍历,动图详解-Java/Kotlin双版本代码

    自古逢秋悲寂寥,我言秋日胜春朝 二叉树结构说明 本博客使用树节点结构,如下所示: Kotlin 版本 class TreeNode(var value: String, var leftNode: T ...

  3. 【树】二叉树遍历算法(深度优先、广度优先遍历,前序、中序、后序、层次)及Java实现...

    [树]二叉树遍历算法(深度优先.广度优先遍历,前序.中序.后序.层次)及Java实现 目录 一.前序遍历 二.中序遍历 三.后序遍历 四.层次遍历 遍历的作用 二叉树是一种非常重要的数据结构,很多其它 ...

  4. 二叉树深度优先 java_二叉树遍历(前序、中序、后序、层次、深度优先、广度优先遍历) java实现...

    二叉树是一种非常重要的数据结构,非常多其他数据结构都是基于二叉树的基础演变而来的.对于二叉树,有深度遍历和广度遍历,深度遍历有前序.中序以及后序三种遍历方法,广度遍历即我们寻常所说的层次遍历.由于树的 ...

  5. java二叉树合并_Java(树的前中后序遍历构造二叉树题型整合)前序和中序、中序和后序、前序和后序遍历序列构造二叉树算法整合归纳...

    前言 二叉树各种花里胡哨的算法题真的把我搞晕了,今天特地整理出一类有关二叉树的算法题,希望能帮助阅读到此文章的人,今后不再受此类题型的困扰. 一.题目类型 已知二叉树的两种遍历序列,请根据该序列构建二 ...

  6. 【LeetCode笔记】94 144 145. 二叉树的前序、中序、后序遍历的迭代与递归(Java、dfs、迭代)

    文章目录 一. 题目描述 二. 代码 & 思路 1. 递归的写法 2. 迭代的写法(本文重点来了) 1) 前序 2) 中序 3) 后序 直接来个整合吧,也方便看.之前只写了递归的,现在补上迭代 ...

  7. 二十五、二叉树的前序、中序、后序遍历

    一.为何使用树这种数据结构 数组存储方式的分析 优点:通过下标方式访问元素,速度快.对于有序数组,还可使用二分查找提高检索速度. 缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较 ...

  8. 手动创建一棵二叉树,然后利用前序、中序、后序、层序进行遍历(从创建二叉树到各种方式遍历)(含运行结果)

    手动创建一棵二叉树,然后利用前序.中序.后序.层序进行遍历 import java.util.LinkedList; import java.util.List; import java.util.Q ...

  9. 把一个数组的值存入二叉树中,然后利用前序、中序、后序3种方式进行遍历(完整代码以及运行结果)(Java)

    把一个数组的值存入二叉树中,然后利用前序.中序.后序3种方式进行遍历(完整代码以及运行结果) 在最近的面试过程中,听说有小伙伴被面试官要求创建二叉树,然后对该二叉树进行遍历,感觉这一直以来都是一个大家 ...

最新文章

  1. java sleep线程吗_JAVA的线程的sleep()方法是否占用CPU
  2. 什么从什么写短句_结婚纪念日发朋友圈说说 致自己结婚纪念日短句 一句话经典...
  3. java bean 单例模式_单例模式 - Beans_bag - 博客园
  4. 《剑指Offer》 调整数组顺序使奇数位于偶数前面
  5. PVS-Studio C/C++/C++11 静态代码分析工具
  6. CXF webservice完整例子
  7. Win10 技巧:让任务栏时间显示 “秒”
  8. php怎么发ddos包,解决服务器上通过PHP代码DDOS的方法
  9. Vue开发警告[Vue warn]: Avoid replacing instance root $data. Use nested data properties instead.
  10. 更改计算机网络,终于理会如何更改计算机网络ip
  11. WSUS服务器不能下载补丁的最终解决办法
  12. 地址转换成百度经纬度,数据太多!不愿意花钱?
  13. 手写在线计算机,在线生成手写签名
  14. vsFTP 基础及实战
  15. 有趣的小游戏——猜数字
  16. 3.3.9 反相积分电路
  17. C++语言程序设计第五版 - 郑莉(第十一章课后习题)
  18. 计算机动画专业要学什么课程,学动画专业的应该用什么什么配置的笔记本电脑?...
  19. 用c语言实现简易三子棋
  20. oracle用户sysman过期,sysman密码过期导致oem无法使用

热门文章

  1. Shellcode拷贝文件
  2. 专业知识感觉什么都会,面试官一问却回答不上来怎么办?
  3. (二)灰度图像二值化
  4. VUE路由的工作原理
  5. 模电基础学习(二)__二极管
  6. 腾讯游戏学院专家:UE高级性能剖析技术之RHI
  7. ACL2020_A Novel Cascade Binary Tagging Framework for Relational Triple Extraction
  8. C语言实现简单计算器程序
  9. 感觉账号被限流了?视频播放量突然变低,看看有没有碰到平台底线
  10. 互联网衰退期,测试工程师35岁之路怎么走...