红黑树(red-black tree)是一种改进的二叉查找树,结点域中增长颜色属性(红或黑)。
二叉查找树的通常操做的时间为 O(lgn)。但若它退化成一棵n个结点的线性链后,操做最坏时间为
O(n)。而红黑树增长了着色和相关性质保证了查找、插入、删除的时间复杂度最坏为 O(lgn).java
特征算法
红黑树和234树是一种等价的数据结构数据结构
红黑树上的search、minimum、maximum、successor、predecessor 能够在 O(logn)内完成。
时间复杂度O(1)
性能
left-rotate(T,x) y=right[x] right[x]=left[x] p[left[y]]=x p[y]=p[x] if p[x]=nil root[T]=y else if x=left[p[x]] left[p[x]]Åy else right[p[x]]=y left[y]=x p[x]=y
jdk8 TreeMap右旋源代码ui
/** From CLR */ private void rotateRight(Entry<K,V> p) { if (p != null) { Entry<K,V> l = p.left; p.left = l.right; if (l.right != null) l.right.parent = p; l.parent = p.parent; if (p.parent == null) root = l; else if (p.parent.right == p) p.parent.right = l; else p.parent.left = l; l.right = p; p.parent = l; } }
主要分两步:.net
二叉查找树的就是一个二分查找,找到合适的位置就放进去。红黑树的插入在二叉查找树插入的基础上,为了从新恢复平衡,继续作了插入修复操做。设计
当咱们往红黑树中插入一个黑色节点时,会打破一个平衡:任一节点到它子树的每一个叶子节点的路径中都包含一样数量的黑节点。
当咱们给一个红色节点下插入一个红色节点时,会打破另外一个平衡:红色节点的左右孩子必定都是黑色节点。
为了简化调整,咱们直接把插入的节点直接染成红色,这样就不会影响上一个平衡,只要专心调整知足后一个平衡就行了。染成红色后,咱们只要关心父节点是否为红,若是是红的,就要把父节点进行变化,让父节点变成黑色,或者换一个黑色节点当父亲,这些操做的同时不能影响 不一样路径上的黑色节点数一致的规则。指针
关注插入节点的父亲节点的位置,而父亲节点位于其爷爷节点地左子树或者右子树的操做是相对称的,座椅只须要研究一侧,即插入位置的父亲节点为左子树。code
插入、染红后的调整有 2 种状况:blog
状况1.父亲节点和叔叔节点都是红色
如上图所示,假设插入的是节点 N,这时父亲节点 P 和叔叔节点 U 都是红色,爷爷节点 G 必定是黑色。
红色节点的孩子不能是红色,这时无论 N 是 P 的左孩子仍是右孩子,只要同时把 P 和 U 染成黑色,G 染成红色便可。这样这个子树左右两边黑色个数一致,也知足特征 4。
可是这样改变后 G 染成红色,G 的父亲若是是红色可能又违反特征 4 了,所以须要以 爷爷节点 G 为新的调整节点,再次进行循环调整操做,直到父亲节点不是红的。
状况2.父亲节点为红色,叔叔节点为黑色
如上图所示,假设插入的是节点 N,这时父亲节点 P 是红色,叔叔节点 U 是黑色,爷爷节点 G 必定是黑色。
红色节点的孩子不能是红色,可是直接把父亲节点 P 涂成黑色也不行,这条路径多了个黑色节点。
经过把 爷爷节点 G 右旋,P 变成了这个子树的根节点,G 变成了 P 的右子树。
右旋后 G 跑到了右子树上,这时把 P 变成黑的,多了一个黑节点,再把 G 变成红的,就平衡了!
上面讲的是插入节点 N 在父亲节点 P 的左孩子位置,若是 N 是 P 的右孩子,就须要多进行一次左旋,把状况化解成上述状况,以下图:
时间复杂度:O(lgn),最多两次旋转
4. 删除
O(lgn)最多三次旋转
5. 查找
O(lgn)
序统计树
序统计就是在一系列数中找出最大、最小值,某个数的序值等操做。
结点域增长size(以x为根的子树所包含的内部结点数,包括x)
操做的时间复杂度O(lgn)
区间树O(lgn)
《算法导论》
https://blog.csdn.net/lanchunhui/article/details/75905478
https://blog.csdn.net/u011240877/article/details/53329023
http://www.javashuo.com/article/p-vrluzavz-ez.html