一. 二叉树概述
二叉树是递归定义的,其节点有左右子树之分
1.1 二叉树特性:
每个节点最多只有两颗子树,节点的度最大为2
左子树和右子树是有顺序的,次序不能颠倒
即使某个节点只有一个子树,也要区分左右子树
1.2 二叉树基本形态:
逻辑上二叉树有五种基本形态:
空二叉树
只有一个根节点的二叉树
只有左子树
只有右子树
完全二叉树
二. 二叉查找树BST
二叉查找树 - BST树:Binary Search Tree,或二叉搜索树
2.1 BST特性:
BST树要么是一颗空树
BST树要么满足以下3个条件的二叉树:
1. 节点的左子树所包含的节点的值都小于该节点的值
2. 节点的右子树所包含的节点的值都大于等于该节点的值
3. 左子树和右子树也都是BST树
2.2 BST优点
二叉查找树这样数据结构有什么好处呢?
我们来试着查找值为11的节点:
a. 查看根节点8
b. 由于11>8,因此查看8节点的右孩子12
c. 由于11<12, 因此查看12节点的左孩子10
d. 由于11>10,因此查看10节点的右孩子11,发现11节点正是需要查找的节点
这种查找方式正是二分查找的思想,查找所需的最大次数等于二叉查找树的高度
2.3 BST缺点
二叉查找树的插入类似于查找,通过一层一层比较大小,找到新节点适合插入的位置
但是二叉查找树存在缺陷:当插入的数据过于特殊,二叉查找树会变瘸,导致空间浪费和查找效率变低
我们来试着看下面的情况:
a. 假设最初的二叉查找树只有3个节点,如图
b. 依次插入如下4个节点:7,6,5,4,结果会变为:
这样的形态虽然也符合二叉查找树的特性,但是浪费空间,查找性能大打折扣
那如何解决二叉查找树因为插入节点而导致的不平衡呢?
这就要用到平衡二叉树了
三. 平衡二叉树
平衡二叉树 - 本质上仍是一颗二叉搜查找树BST
3.1 平衡二叉树特性:
AVL树首先是二叉查找树BST
带有平衡条件:任何节点的左右子树的高度之差的绝对值(平衡因子)最多为1
3.2 平衡二叉树常用实现:
平衡二叉树的常用实现方法有红黑树、AVL树、替罪羊树、Treap、伸展树等
红黑树(red black tree)
游戏规则:
- 节点是红色或者黑色
- 根节点是黑色
- 每个叶子节点都是黑色的空节点(NULL节点)
- 每个红色节点的两个子节点都是黑色(从根到每个叶子节点的所有路径上不能有两个连续的红色节点)
- 从任一节点到该节点的每个叶子节点的所有路径都包含相同数目的黑色节点
:旋转的方向。
:变换过程。
:互相关联。
:单向关联。
:代表红色的节点。
:代表黑色的节点。
和:代表一个不会破坏红黑树结构的部分,可能是节点,或者是一个子树,总之不会破环当前树的结构。这个部分会由于旋转而连接到其他的节点后面,我们可以理解成由于重力原因它掉到了下面的节点上。
- 单旋转变换。
- 双旋转变换(需要两次反方向的单旋转)。
- 当遇到两个子几点都为红色的话执行颜色变换,因为插入 是红色的会产生冲突。如果根节点两边的子节点都是红色,两个叶子节点变成黑色,根节点变成红色,然后再将根节点变成黑色。
为什么要进行旋转?
由于P和X节点都为红色节点这破环了红节点下面的节点必须为黑色节点的规则。
新加入的节点总是红色的,这是为什么呢?
因为被插入前的树结构是构建好的,一但我们进行添加黑色的节点,无论添加在哪里都会破坏原有路径上的黑色节点的数量平等关系,所以插入红色节点是正确的选择。
为什么要进行颜色变换?
正如第一种旋转新加入的节点X破坏了红黑树的结构不得不进行旋转,后面的就是旋转后的结果,旋转后形成新的结构,此时我们发现两个子节点都是红色的所以执行第三个变换特性,颜色变换,因为如果子节点是红色的那么我们在添加的时候只能添加黑色的节点,然而添加任何黑色叶子节点都会破坏树的第四条性质,所以要对其进行变换。当进行变换后叶子节点是红色的而且我们默认添加的叶子节点是红色的,所以添加到黑色节点后并不会破坏树的第四条结构,所以这种变换很有用。
第二种双变换中在树的内部怎么出现的红色的节点?
正是由于上面的颜色变换导致新颜色变换后的节点与他的父节点产生了颜色冲突。