树
树是n(n>=0)个节点的有限集,当n=0时 称为空树。在任意一个非空树中,有如下特点:
- 有且只有一个根节点
- 当n>1时,其余节点可分为m(m>0)个互不相交的有限集,每一个集合本身又是一棵树,称为根的子树
二叉树
二叉树是树的一种特殊形式,这种树的每个节点最多有2个孩子节点。最多有2个,也可能只有1个,或者没有孩子节点。
二叉树还有两种特殊形式,一个叫做满二叉树,另一个叫做完全二叉树
满二叉树
一个二叉树的所有非叶子节点都存在左右孩子,并且所有叶子节点都在同一层级,那么这个树就叫做满二叉树
也就是锁 满二叉树的每一个分支都是满的
完全二叉树
对一个有n个节点的二叉树,按层级顺序编号,则所有节点的编号为从1到n。如果这个树所有节点和同样深度的满二叉树的编号为从1到n的节点位置相同,则这个二叉树为完全二叉树
如上 这是一个完全二叉树
如上 这不是一个完全二叉树,同样也不是满二叉树 因此只能称为二叉树吧
二叉查找树(binary search tree)
二叉查找树在二叉树的基础上增加了以下条件:
- 如果左子树不为空 则左子树上的所有节点的值均小于根节点的值
- 如果右子树不为空 则右子树上所有节点的值均大于根节点的值
- 左右子树也是二叉查找树
二叉查找树 在一定程度上可以减少遍历的次数,因为其先天条件决定,小于根节点的元素在左子树,大于根节点的元素在右子树,因此可以看做是二分查找,理想条件下时间复杂度O(logn)
特殊情况:
全部节点集中在右子树上,这种情况下 遍历就像是遍历链表一样,时间复杂度O(n) 不太理想
平衡二叉树(AVL)
首先强调一下 平衡二叉树 也是一种二叉查找树
节点的高度差不超过1(即平衡因子为-1,0,1) ,否则会将最小的不平衡子树进行旋转 来重新构造子树,维持节点高度差不超过1的规则
正因为平衡二叉树对平衡极致的追求,我们知道越极致的平衡 越容易被打破 所以这里引入了旋转策略 来将不平衡的树再次变为平衡
- LL 在子节点的左子树上插入左子节点 导致失衡 右旋转
将节点2插入树之后 树结构变为上图所示
我们知道 这个时候节点6的高度差是2 已经是不平衡状态了,根节点8的高度差也是3 也不平衡了,我们需要做的是 找到最小不平衡树 将其变为平衡 再寻找是否还有不平衡子树存在 直至将树变为平衡
这里2,4,6 为最小不平衡树 将这个子树按照添加2元素的根节点4右旋
将旋转后的子树 放入原树中 发现原树已经达到平衡 因此不需要再做额外的旋转了
- RR 在子节点的右子树上插入右子节点 导致失衡 左旋转
原树保持平衡,在插入节点14之后,节点10的高度差为2,是最小不平衡树,这里将10、12、14以12为中心进行坐旋转
将旋转后的子树放入原树中,发现原树已经平衡 因此不需要额外的操作
LL的特例:
插入节点5之后 树已经变得不平衡了。节点6的高度差为1 等于说以6为根节点的子树 是平衡的。
节点8的高度差是2 那么以8为根的左子树不平衡了。
这里是在子节点6的左子树上插入右子节点,因此现将6这个子树按照6为中心进行右旋
(这里的不平衡树是以8为根节点的树 因此从8的角度看 是在左子树上插入节点)
-
LR 在某节点的左子树上插入右子节点 导致失衡 先左旋再右旋
-
RL 在某节点的右子树上插入左子节点 导致失衡 先右旋再左旋
由于 不太好举例子 这里就以LR举例说明吧
旋转点的判断:一般是在某个节点插入子节点后 导致失衡 那么这个节点很可能是旋转点;或者最小不平衡树的根节点或其直接子节点。也需要根据实际情况分析
红黑树
红黑树 也是一种二叉查找树 是一种大致平衡的二叉查找树。其遵循以下规则:
- 根节点必须是黑色
- 每个节点颜色要么是黑色要么是红色
- 每个叶结点(实际上就是NULL指针)都是黑色的。
- 如果一个节点的颜色是红色,那么它的两个子节点都是黑色
- 从任一节点 到其所有子孙节点的普通路径中所包含的黑色节点个数都是相等的
红黑树对于平衡的要求 没有AVL树那么强。红黑树在维护平衡的时候 也可以使用左旋、右旋等
由于红黑树的设计,任何不平衡都会在三次旋转之内解决(插入最多只需要两次,删除最多需要三次)。这样也保证了它的性能。
为什么红黑树的统计性能优于AVL树?
-
如果插入一个node引起了树的不平衡,AVL和红黑树都是最多只需要2次旋转操作,以及O(logN)的遍历时间。但是在删除node引起树的不平衡时,最坏情况下,AVL需要维护从实际被删node的父节点到root这条路径上所有node的平衡性,因此需要若干次的旋转以及O(logN)的遍历时间。而红黑树最多只需3次旋转,以及O(logN)的遍历时间。
-
其次,AVL的结构相较红黑树来说更为平衡,在插入和删除node更容易引起Tree的unbalance,因此在大量数据需要插入或者删除时,AVL需要rebalance的频率会更高。因此,红黑树在需要大量插入和删除node的场景下,效率更高。
-
由于AVL高度平衡,因此AVL的search效率更高。红黑树的查询性能略微逊色于AVL树,因为他比AVL树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的avl树最多多一次比较