树的结构,如果不能保持平衡,那么其搜索性能会大大打折扣,而本节课介绍了几种经典的平衡树,如AVL,2-3-4tree,红黑树等等,然后着重讲了红黑树,接下来就红黑树的基本性质,作一些简短的总结。
首先,红黑树除了具有BST的基本性质外,还额外拥有以下的五大基本性质:
1)每个结点有一个色域,一个结点要么为黑结点,要么为红结点
2)根节点为黑结点
3)每个叶子结点都为黑结点(无键值)
4)每个红结点的父亲都为黑结点,即不可能出现两个红色结点相连的情况
5)从根节点到任意叶节点的路径中的黑色结点数目相等,这个数目也称为黑高度
由以上5点性质,可以保证红黑树的高度为O(lgn),证明如下:
将红黑树的所有红结点,都与其父节点(由性质四得其父节点必定为黑)合并,可以得到一颗2-3-4 tree(即每个结点的子节点数目为2~4个),由数据结构知识可得,原红黑树的叶子结点个数为带键值结点个数n+1,假设整棵树高度为h,那么叶子结点数应为h^2~h^4,因此有h^2<=n+1<=h^4,即此时树高度最高也只有log
n+1,即树的黑高度为log n+1,根据性质3,树最高情况也不过是红黑相间的时候,因此其高度最高只有2log n+1 ,即树的高度为O(lgn)。
红黑树的查询操作和普通BST一样,而删除和插入操作则相对复杂,因为我们要保证红黑树的5大性质,为什么需要保证这五大性质呢?因为这五大性质是红黑树为平衡树的保证,能够保证红黑树的高度为Olgn,这样红黑树的基本操作(删,插,查)都可以保证在Olgn的时间复杂度内完成。
接下来简单介绍一下插入操作是如何完成的,删除操作思路类似:
插入操作的原理就是插入一个红结点,然后通过向上重染色和旋转的方式维持红黑树的性质
这里有三种情况
case1 直线型 且祖父结点为黑,父节点和父亲兄弟结点为红 将祖父结点的黑传递到两个红子节点 每次向上传
递2个结点,树高度2lgn 所以操作为O(lgn)
case2 zigzag Z型 父亲兄弟结点为黑 旋转为case3 O(1)的旋转
case3 zigzig直线型 旋转
由以上三种情况可得,插入的时间复杂度为重染色的Olgn+不超过3次的O(1)的旋转操作
这里值得一提的是,在实际的运用中,虽然向上重染色理论上花费的时间多于旋转,但是当多个用户并发查询访问红黑树的时候,重染色并不会影响查询,因为用户并不关心每个结点的颜色,但是旋转需要锁定该子树及其结点,可能会影响并发查询的操作。
最后,就AVL和红黑树做一下比较,就平衡程度而言,AVL是追求的绝对平衡,任意叶子结点的深度不会多于其他叶子结点深度+1,而红黑树只要求局部平衡,其红黑性保证了其平衡性,因此在维护平衡方面,红黑树只需要不超过3次旋转即可,这一点是AVL树所做不到的,但查询方面,由于AVL是绝对平衡,因此效率会略高于红黑树,实际应用中这一点并不明显,就统计性能而言,红黑树会优于AVL,而C++
STL中的set、multiset、map、multimap等,都是红黑树的一种变体。
值得一提的是,平衡树都是动态的数据结构,其优势在于动态操作下,也能保持优越的查询效率,如果是静态数据,那么使用hash表效率会更高一些。