二叉树
定义:
二叉树(Binary Tree) 是n(n>=0)个节点的有限集合,该集合可以为空集(称为空二叉树),或者由一个根节点和两个互不相交的节点(分别称为根节点的左子树和右子树的二叉树组成)。
特征:
- 每个节点最多有两个子树,所以二叉树不存在度大于2的节点(结点的度:结点拥有的子树的数目),可以没有子树或者一个子树。
- 左子树和右子树有顺序,次序不能任意颠倒。
- 即使树中某节点只有一颗子树,也要区分是左子树还是右子树。
性质:
- 二叉树第i层上的结点数目最多为 2{i-1} (i≥1)
- 深度为k的二叉树至多有2{k}-1个结点(k≥1)
- 在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1
- 包含n个结点的二叉树的高度至少为log2 (n+1)
5种基本形态:
- 空二叉树
- 只有一个根节点
- 根节点只有左子树
- 根节点只有右子树
- 根节点既有左子树,又有右子树
特殊二叉树
-
斜树:所有节点都只有左子树的二叉树叫左斜树,所有节点都只有右子树的二叉树叫右斜树。
-
满二叉树:在一棵二叉树中如果所有分支节点都存在左子树和右子树并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
-
完全二叉树:对于一棵具有n个节点的二叉树按层次编号,如果编号为i(1<=i<=n)的节点与同样深度的满二叉树中编号为i的节点在二叉树中位值完全相同,则这棵二叉树称为完全二叉树。
二叉查找树
特点
- 左子树不为空,则左子树上节点的值都小于根节点
- 右子树不为空,则右子树上节点的值都大于根节点
- 子树同样遵循以上两点
注:中序遍历一定是有序的
[二叉查找树] VS [红黑树]
二叉查找树 : 不一定平衡,在某些条件下会退化成链表
平衡二叉树
AVL (平衡树 )包括:红黑树、绝对平衡树
二叉平衡树:首先,是二叉查找树;其次,它是平衡的。
/**
* AVL(平衡二叉树)
* 左右子树的高度差不会超过1[会通过左旋右旋操作是树平衡]
* 缺点:生成过程繁琐
*/
红黑树:是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组
/**
* 红黑树(RBT),只要求黑节点平衡即可
*/
优点:查找快
缺点:插入慢
红黑树和二叉平衡树区别:
红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单。
平衡二叉树追求绝对平衡,条件比较苛刻,实现起来比较麻烦,每次插入新节点之后需要旋转的次数不能预知。
关于索引:
红黑树为何不适合做索引:
- 红黑树基本都是存储在内存中才会使用的数据结构。
- 在大规模数据存储的时候,红黑树往往出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况。
为什么会出现这样的情况,我们知道要获取磁盘上数据,必须先通过磁盘移动臂移动到数据所在的柱面,然后找到指定盘面,接着旋转盘面找到数据所在的磁道,最后对数据进行读写。磁盘IO代价主要花费在查找所需的柱面上,树的深度过大会造成磁盘IO频繁读写。根据磁盘查找存取的次数往往由树的高度所决定,所以,只要我们通过某种较好的树结构尽量减少树的高度,B树可以有多个子女,从几十到上千,可以降低树的高度。
B树
种类
1、B-Tree (B树)
2、B+Tree(B+树)
3、BTree (B树) // 基本不用
特征
- 节点最多含有m棵子树(指针),m-1个关键字(存的数据,空间)(m>=2)
- 除根节点和叶子结点外,其它每个节点至少有ceil(m/2)
- 若根节点不是叶子节点,则至少有两棵子树
插入方式
从根节点开始查找,一直找到对应的地方进行插入
注: B树有个阶,多少阶就有多少棵子树。(存多少数据)
例如:5阶B树最多有5个指针(子树)存查找路径,存4个数据和5个指针
不适合做mysql索引,一下两个原因影响IO:
- 每个节点都有数据
- 层高太高
B+树
特性
- 每个节点最多有m个子节点
- 除根节点外,每个节点至少有m/2个子节点,注意如果结果除不尽,就向上取整;比如5/2=3
- 根节点要么是空,要么是独根,否则至少有2个子节点
- 有K个子节点的节点必有K个关键码
- 叶子节点的高度一致
特征
- 数据只存在叶子节点
- 叶子节点之间有一个双向链表,方便索引
- 子节点最右边一个数据都能在父节点中找到(索引的本质,同时还满足了范围查找,索引没有数据)
插入方式
从叶子节点查找
总结
二叉查找树、红黑树、B-Tree、B+Tree的区别:
二叉查找树
二叉查找树又叫二叉搜索树,优点查找快,但是在某些情况下会退化成链表,它是所有高效查找树的基础,如果不懂这个,其他的也学不懂。根本性的东西,最好能自己手写出来。
红黑树
内存查找高效树,不适合大数据量,也不适合磁盘存储的。具体的分析就是IO浪费以及读取资源浪费,还有就是树的深度会很大。适合一些底层系统做内存运算。
B-Tree
可以认为是B+Tree过度,只需要知道BTree就可以。
B+Tree
最适合大数据的磁盘索引,经典的MySQL,所有的数据都存在叶子节点,其他都是索引,增加了系统的稳定性以及遍历和查找效率。
B-Tree 和 B+Tree 不同点:
- 关键字和Key值一样
- 数据存储的地方(B-Tree每个节点都有;B+Tree只在叶子节点)
- B+Tree在叶子节点有双向链表
B-Tree 和 B+Tree 相同点:
相同点很多!最主要的是都有一个阶的概念。
M阶:这个由磁盘的页码大小决定,磁盘块和页内存一般都是4KB。我们节点数也就是我们的M值,应该要尽可能的跟他一样。例如,数据库会在阶的概念上加一个加载因子,1或者0.75的原则(根据表的字段数据大小设定一个阶)。HashMap也会有类似的加载因子,不会一次加载满。这样的好处就是为了我们一次刚好能全部拿出一个节点里面存的所有数据,不需要多次取数。
HashMap
实现方式
两种方法:
- 数组+链表
- 红黑树
节点组成
{
key,
value,
hash, # 找到数组对应的位置,也就是对应的链表头(该值是通过key算出来的)
next # 指向下一个
}
数组+链表 [VS] 红黑树