树的基本概念以及java实现二叉树
树具有的特点有:
(1)每个结点有零个或多个子结点
(2)没有父节点的结点称为根节点
(3)每一个非根结点有且只有一个父节点
(4)除了根结点外,每个子结点可以分为多个不相交的子树。
树的基本术语有:
若一个结点有子树,那么该结点称为子树根的“双亲”,子树的根称为该结点的“孩子”。有相同双亲的结点互为“兄弟”。一个结点的所有子树上的任何结点都是该结点的后裔。从根结点到某个结点的路径上的所有结点都是该结点的祖先。
结点的度:结点拥有的子树的数目
叶子结点:度为0的结点
分支结点:度不为0的结点
树的度:树中结点的最大的度
层次:根结点的层次为1,其余结点的层次等于该结点的双亲结点的层次加1
树的高度:树中结点的最大层次
森林:0个或多个不相交的树组成。对森林加上一个根,森林即成为树;删去根,树即成为森林。
二叉树的性质
a、在非空二叉树的第i层上,至多有2^(i-1)个结点
假设这是一棵满二叉树,则1、2、3层分别有1、2、4个结点,满足以上性质
b、深度为k的二叉树至多有2^k-1个结点
假设这是一棵满二叉树,则4层有15个结点,满足以上的性质
c、对任何一颗二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0 = n2+1
假设二叉树中度为1的结点数为n1,因为二叉树只有度为1,2,0的结点,所以有n=n0+n1+n2。再看二叉树分支条数e,因为二叉树除了根结点没有父结点,进入它的边数为0之外,其他每一结点都有一个且仅有一个父结点,进入它们的边数均为1,故二叉树中总的边数为e=n-1=n0+n1+n2-1。又由于每个度为2的结点发出2条边,每个度为1的结点发出1条边,每个度为0的结点发出0条边,因此总的边数e=2n2+1n1+0n0=2n2+n1,由以上两式可以得出n0= n2+1
上图中结点总数是10,n2(1、2、3、4)为4,n1(5)为1,n0(6、7、8、9、10)为5
d、具有n个结点的完全二叉树深度为⌈log2(n+1)⌉,对以2为底n+1对数进行向上取整(⌈⌉是向上取整符号)
可以由性质2得出,深度为k的完全二叉树最多有 n \leq 2{k}-1个结点,最少有2{k-1}-1个,因此:
2^{k-1}-1 < n \leq 2^{k}-1
2^{k-1} < n+1 \leq 2^{k}
k-1 < log_{2}(n+1) \leq k
因为log_{2}(n+1)介于 K-1 和 K之间且不等于 K-1,深度又只能是整数,所以有⌈log_{2}(n+1)⌉
e、如果有一颗有n个结点的完全二叉树的结点按层次序编号,对任一层的结点i(1<=i<=n)有
如果i=1,则结点是二叉树的根,无双亲,如果i>1,则其双亲结点为⌊i/2⌋,向下取整
如果2i>n那么结点i没有左孩子,否则其左孩子为2i
如果2i+1>n那么结点没有右孩子,否则右孩子为2i+1
若结点i为奇数,且i!=1,它处于右兄弟位置,则它的左兄弟结点i-1
若结点i为偶数,且i!=n,它处于左兄弟位置,则它的右兄弟为结点i+1
https://github.com/mcrwayfun/java-data-structure/blob/master/doc/source/tree/树.md#23-二叉树的性质
递归实现二叉树的遍历
前序遍历
基本思想:若二叉树为空,则返回。否则从根结点开始,优先访问根结点,再前序遍历左子树,前序遍历右子树,即根——左——右
class TreeNode{
int data;
TreeNode leftChild;
TreeNode rightChild;
}
/**
* 前序遍历(中左右)
* output:A、B、D、G、H、C、E、I、F
* @param root
*/
public void preOrder(TreeNode root) {
if (root == null) {
return;
} else {
System.out.println("preOrder data:" + root.getData());
preOrder(root.leftChild);
preOrder(root.rightChild);
}
}
中序遍历
基本思想:若二叉树为空,则返回。否则优先中序遍历左子树,再访问根结点,再后序遍历右子树,即左——根——右
/**
* 中序遍历(左中右)
* output:G、D、H、B、A、E、I、C、F
* @param root
*/
public void midOrder(TreeNode root) {
if (root == null) {
return;
} else {
midOrder(root.leftChild);
System.out.println("midOrder data:" + root.getData());
midOrder(root.rightChild);
}
}
后序遍历
基本思想:若二叉树为空,则返回。否则优先后序遍历左子树,再后序遍历右子树,最后访问根结点,,即左——右——根
/**
* 后序遍历(左右中)
* output:G、H、D、B、I、E、F、C、A
* @param root
*/
public void postOrder(TreeNode root){
if (root == null) {
return;
} else {
postOrder(root.leftChild);
postOrder(root.rightChild);
System.out.println("postOrder data:" + root.getData());
}
}
满二叉树、完全二叉树和二叉查找树、 2-3查找树
1、满二叉树
定义:高度为h,并且由2h-1个结点组成的二叉树,称为满二叉树
2、完全二叉树
定义:一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下层的叶结点集中在靠左的若干位置上,这样的二叉树称为完全二叉树。
特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。
3、二叉查找树
定义:二叉查找树又被称为二叉搜索树。设x为二叉查找树中的一个结点,x结点包含关键字key,结点x的key值计为key[x]。如果y是x的左子树中的一个结点,则key[y]<=key[x];如果y是x的右子树的一个结点,则key[y]>=key[x]
在二叉查找树种:
(1)若任意结点的左子树不空,则左子树上所有结点的值均小于它的根结点的值。
(2)任意结点的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
(3)任意结点的左、右子树也分别为二叉查找树。
(4)没有键值相等的结点。
https://blog.csdn.net/javazejian/article/details/53727333
2-3查找树
对于2节点,该节点保存一个key及对应value,以及两个指向左右节点的节点,左节点也是一个2-3节点,左节点所有的值都比该节点的key要小,右节点也是一个2-3节点,所有的值比该节点的key要大。
对于3节点,该节点保存两个key及对应value,以及三个指向左中右的节点。左节点也是一个2-3节点,所有的值均比两个key中的最小的key还要小;中间节点也是一个2-3节点,中间节点的key值在两个跟节点key值之间;右节点也是一个2-3节点,节点的所有key值比两个key中的最大的key还要大。
平衡二叉树 、 红黑树、替罪羊树、Treap、伸展树
平衡二叉树是一种特殊的二叉搜索树,在按顺序向插入二叉搜索树中插入值,最后会形成一个类似链表形式的树,而我们设计二叉搜索树的初衷,显然是看中了它的查找速度与它的高度成正比,如果每一颗二叉树都像链表一样,那就没什么意思了,所以就设计出来了平衡二叉树,相对于二叉搜索树,平衡二叉树的一个特点就是,在该树中,任意一个节点,它的左右子树的差的绝对值一定小于2。
1.本身首先是一棵二叉搜索树。
2.带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。
也就是说,AVL树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树)。
AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。
如果在AVL树中插入或删除节点后,使得高度之差大于1。此时,AVL树的平衡状态就被破坏,它就不再是一棵平衡二叉树;为了让它重新维持在一个平衡状态,就需要对其进行旋转处理
平衡二叉树的旋转
左-左型:做右旋
右-右型:做左旋
左-右型:先做左旋,后做右旋
右-左型:先做右旋,后做左旋
这里假设结点X是失衡点,它必须重新恢复平衡,由于任意结点的孩子结点最多有两个,而且导致失衡的必要条件是X结点的两棵子树高度差为2(大于1),因此一般只有以下4种情况可能导致X点失去平衡:
① 在结点X的左孩子结点的左子树中插入元素
② 在结点X的左孩子结点的右子树中插入元素
③ 在结点X的右孩子结点的左子树中插入元素
④ 在结点X的右孩子结点的右子树中插入元素
以上4种情况,其中第①情况和第④情况是对称的,可以通过单旋转来解决,而第②种情况和第③情况是对称的,需要双旋转来解决。
左左单旋转(LL)需要右旋转
右右单旋转(RR)进行左旋转
https://blog.csdn.net/javazejian/article/details/53892797
https://www.jb51.net/article/154428.htm
https://blog.csdn.net/cqulun123/article/details/80399371
https://blog.csdn.net/m1179457922/article/details/81745013
https://blog.csdn.net/genius_wolf/article/details/85267253
https://www.jianshu.com/p/4f5eca987990
https://www.cnblogs.com/qm-article/p/9349681.html
https://blog.csdn.net/m0_38036210/article/details/100517125
《剑指offer》
https://www.cnblogs.com/mingyueanyao/p/10322643.html
https://algs4.cs.princeton.edu/33balanced/
http://pages.cs.wisc.edu/~ealexand/cs367/NOTES/AVL-Trees/index.html
https://visualgo.net/en/bst
红黑树
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
平衡树(AVL)是为了解决 二叉查找树(BST)退化为链表的情况。
红黑树(RBT)是为了解决 平衡树 在删除等操作需要频繁调整的情况。
红黑树5个特征
红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
节点是红色或黑色。
根节点是黑色。
每个叶节点(NIL节点,空节点)是黑色的。
每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
红黑树是一种具有红色和黑色链接的平衡查找树,同时满足:
红色节点向左倾斜
一个节点不可能有两个红色链接
整个树完全黑色平衡,即从根节点到所以叶子结点的路径上,黑色链接的个数都相同。
如果我们将红色的连线水平绘制,那么他链接的两个2-node节点就是2-3树中的一个3-node节点了。
红黑树的应用比较广泛,主要是用它来存储有序的数据,它的时间复杂度是O(logn),效率非常之高。
例如,Java集合中的TreeSet和TreeMap,C++ STL中的set、map,以及Linux虚拟内存的管理,都是通过红黑树去实现的。
https://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html
https://blog.csdn.net/eson_15/article/details/51144079
https://blog.csdn.net/v_july_v/article/details/6105630
平衡二叉树红黑树两者的区别
1、红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。红黑树能够以O(log2 n) 的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。当然,还有一些更好的,但实现起来更复杂的数据结构 能够做到一步旋转之内达到平衡,但红黑树能够给我们一个比较“便宜”的解决方案。红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高。当然,红黑树并不适应所有应用树的领域。如果数据基本上是静态的,那么让他们待在他们能够插入,并且不影响平衡的地方会具有更好的性能。如果数据完全是静态的,例如,做一个哈希表,性能可能会更好一些。在实际的系统中,例如,需要使用动态规则的防火墙系统,使用红黑树而不是散列表被实践证明具有更好的伸缩性,典型的用途是实现关联数组。
2、AVL树是最先发明的自平衡二叉查 找树。在AVL树中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
B树、B_树、B+树
B树(B-tree)是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作。B-tree算法减少定位记录时所经历的中间过程,从而加快存取速度。普遍运用在数据库和文件系统。”
定义
B 树可以看作是对2-3查找树的一种扩展,即他允许每个节点有M-1个子节点。
根节点至少有两个子节点
每个节点有M-1个key,并且以升序排列
位于M-1和M key的子节点的值位于M-1 和M key对应的Value之间
其它节点至少有M/2个子节点
https://blog.csdn.net/u012124438/article/details/78109466
https://article.itxueyuan.com/wy3Bon
https://segmentfault.com/a/1190000020416577?utm_source=tag-newest
https://www.iteye.com/blog/uule-2429508
https://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html
B+树
B+树是对B树的一种变形树,它与B树的差异在于:
有k个子结点的结点必然有k个关键码;
非叶结点仅具有索引作用,跟记录有关的信息均存放在叶结点中。
树的所有叶结点构成一个有序链表,可以按照关键码排序的次序遍历全部记录。
https://blog.csdn.net/qingtian_1993/article/details/80637917
https://segmentfault.com/a/1190000014743964
https://github.com/mcrwayfun/java-data-structure/blob/master/doc/source/tree/树.md
https://blog.csdn.net/m0_38036210/article/category/9225624
树的基本概念以及java实现二叉树的更多相关文章
- 数据结构与算法->树->2-3-4树的查找,添加,删除(Java)
代码: 兵马未动,粮草先行 作者: 传说中的汽水枪 如有错误,请留言指正,欢迎一起探讨. 转载请注明出处. 目录 一. 2-3-4树的定义 二. 2-3-4树数据结构定义 三. 2-3-4树的可以得到 ...
- 异常的概念和Java异常体系结构
一. 异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架, 是Java语言健壮性的一个重要体现. Ja ...
- Java实现二叉树及相关遍历方式
Java实现二叉树及相关遍历方式 在计算机科学中.二叉树是每一个节点最多有两个子树的树结构.通常子树被称作"左子树"(left subtree)和"右子树"(r ...
- 数据结构(5):Java实现二叉树
二叉树图: package com.test.Sort; import java.util.ArrayList; import java.util.LinkedList; public class B ...
- java实现二叉树的Node节点定义手撕8种遍历(一遍过)
java实现二叉树的Node节点定义手撕8种遍历(一遍过) 用java的思想和程序从最基本的怎么将一个int型的数组变成Node树状结构说起,再到递归前序遍历,递归中序遍历,递归后序遍历,非递归前序遍 ...
- JVM 内部原理(五)— 基本概念之 Java 虚拟机官方规范文档,第 7 版
JVM 内部原理(五)- 基本概念之 Java 虚拟机官方规范文档,第 7 版 介绍 版本:Java SE 7 每位使用 Java 的程序员都知道 Java 字节码在 Java 运行时(JRE - J ...
- java创建二叉树并实现非递归中序遍历二叉树
java创建二叉树并递归遍历二叉树前面已有讲解:http://www.cnblogs.com/lixiaolun/p/4658659.html. 在此基础上添加了非递归中序遍历二叉树: 二叉树类的代码 ...
- java实现二叉树查找树
二叉树(binary)是一种特殊的树.二叉树的每个节点最多只能有2个子节点: 二叉树 由于二叉树的子节点数目确定,所以可以直接采用上图方式在内存中实现.每个节点有一个左子节点(left childre ...
- 哈弗曼树的理解和实现(Java)
哈弗曼树概述 哈弗曼树又称最优树,是一种带权路径长度最短的树,在实际中有广泛的用途.哈弗曼树的定义,涉及路径.路径长度.权等概念.哈弗曼树可以用于哈弗曼编码,用于压缩,用于密码学等. 哈弗曼树的一些定 ...
随机推荐
- 2019 NCTF Re WP
0x01 debug 测试文件:https://www.lanzous.com/i7kr2ta 1.Linux运行环境 在Linux上运行linux_server64文件 2.IDA配置 __int6 ...
- OC中数组排序的3种方法
总结OC中数组排序3种方法:sortedArrayUsingSelector:;sortedArrayUsingComparator:;sortedArrayUsingDescriptors: 大体上 ...
- Apache 的 php.ini 配置文件详解
[root@taokey ~]# grep -v ";" /application/php/lib/php.ini [PHP] engine = On ——→ 是否启用 PHP ...
- Codeforces 962 /2错误 相间位置排列 堆模拟 X轴距离最小值 前向星点双连通分量求只存在在一个简单环中的边
A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...
- GUI学习之二十九—QFileDialog学习总结
今天学习的是文件对话框——QFileDialog 一.描述 QFileDialog提供了一个对话框,允许用户选择文件或者目录,也允许用户遍历文件系统,用以选择一个或多个文件或者目录. QFileDia ...
- 面向对象原生js轮播图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ZROI 19.07.30 简单图论/kk
1.最短路 NOI2019 D2T1 我被这题送Fe了/lb 只有zz才会写二维线段树,比如我. 实际上你只需要矩形取min就可以. kd-tree可以随便过,最慢的点\(0.1s\). 另外一种简单 ...
- mongdb 学习
一:安装1.首先到官网(http://www.mongodb.org/downloads )下载合适的安装包2.安装mongodb3. cmd 命令切换到安装目录bin 下面 mongod --dbp ...
- POJ-3436-ACM Computer Factory(最大流, 输出路径)
链接: https://vjudge.net/problem/POJ-3436#author=0 题意: 为了追求ACM比赛的公平性,所有用作ACM比赛的电脑性能是一样的,而ACM董事会专门有一条生产 ...
- Python---进阶---函数式编程---lambda
一. 利用map()函数,把用户输入的不规范的英文,变成首字母大写,其他小写的规范的名字:比如说["ADMAm", "LISA", "JACK&quo ...