最近在研究map和unordered_map,接触到了红黑树这个东西..大学一直想学而始终没学,因此学习学习 感谢做者
html
1,http://blog.csdn.net/v_JULY_v/article/details/6105630node
2,http://blog.csdn.net/v_JULY_v/article/details/6109153算法
3,http://blog.csdn.net/v_JULY_v/archive/2011/01/03/6114226.aspx学习
4,http://blog.csdn.net/v_JULY_v/archive/2011/01/09/6124989.aspxspa
5,http://blog.csdn.net/v_JULY_v/article/details/6284050.net
6,http://blog.csdn.net/v_JULY_v/article/details/6285620指针
红黑树是一种二叉查找树,但在每一个结点上增长一个存储位表示结点的颜色,能够是Red或Black。经过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其余路径长出俩倍,于是是接近平衡的。code
红黑树,做为一棵二叉查找树,知足二叉查找树的通常性质。下面,来了解下 二叉查找树的通常性质。htm
二叉查找树,也称有序二叉树(ordered binary tree),或已排序二叉树(sorted binary tree),是指一棵空树或者具备下列性质的二叉树:blog
由于一棵由n个结点随机构造的二叉查找树的高度为log2n,因此瓜熟蒂落,二叉查找树的通常操做的执行时间为O(log2n)。但二叉查找树若退化成了一棵具备n个结点的线性链后,则这些操做最坏状况运行时间为O(n)。(当二叉查找树是平衡二叉查找树[AVL]的时候时间复杂度是O(log2n),而斜树的时候是O(n)
二叉平衡树: 它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,而且左右两个子树都是一棵平衡二叉树。构造与调整方法 平衡二叉树的经常使用算法有红黑树、AVL、Treap等。 |
红黑树虽然本质上是一棵二叉查找树,但它在二叉查找树的基础上增长了着色和相关的性质使得红黑树相对平衡,从而保证了红黑树的查找、插入、删除的时间复杂度最坏为O(log n)。
但它是如何保证一棵n个结点的红黑树的高度始终保持在logn的呢?这就引出了红黑树的5个性质:
正是红黑树的这5条性质,使一棵n个结点的红黑树始终保持了logn的高度,从而也就解释了上面所说的“红黑树的查找、插入、删除的时间复杂度最坏为O(log n)”这一结论成立的缘由。
(注:上述第三、5点性质中所说的NULL结点,包括wikipedia.算法导论上所认为的叶子结点即为树尾端的NIL指针,或者说NULL结点。然百度百科以及网上一些其它博文直接说的叶结点,则易引发误会,因,此叶结点非子结点)
以下图所示,便是一颗红黑树(下图引自wikipedia:http://t.cn/hgvH1l):
此图忽略了叶子和根部的父结点。同时,上文中咱们所说的 "叶结点" 或"NULL结点",如上图所示,它不包含数据而只充当树在此结束的指示,这些节点在绘图中常常被省略,望看到此文后的读者朋友注意。(上图 NIL是NULL也就是最后的叶节点只不过这个是实现为NULL值,仍是一个假节点,看你喜欢了)
2、树的旋转知识
当在对红黑树进行插入和删除等操做时,对树作了修改可能会破坏红黑树的性质。为了继续保持红黑树的性质,能够经过对结点进行从新着色,以及对树进行相关的旋转操做,即经过修改树中某些结点的颜色及指针结构,来达到对红黑树进行插入或删除结点等操做后继续保持它的性质或平衡的目的。
树的旋转分为左旋和右旋,下面借助图来介绍一下左旋和右旋这两种操做。
1.左旋
如上图所示,当在某个结点pivot上,作左旋操做时,咱们假设它的右孩子y不是NIL[T],pivot能够为任何不是NIL[T]的左子结点。左旋以pivot到Y之间的链为“支轴”进行,它使Y成为该子树的新根,而Y的左孩子b则成为pivot的右孩子。
1 LeftRoate(T, pivot) 2 y <- pivot.right //定义y: y是x的右孩子 3 pivot.right <- y.left //y的左孩子成为x的右孩子 4 5 if y.left ≠ T.nil 6 y.left.paret <- pivot 7 y.paret <- x.paret //x的父节点成为y的父节点 8 if pivot.paret = T.nil 9 then T.root <-- y 10 else if pivot = pivot.paret.left 11 then pivot.paret.right <-- y 12 else pivot.paret.right <-- y 13 y.left <-- pivot //x做为y的左孩子 14 pivot.paret <-- y
2.右旋 右旋与左旋差很少,再次不作详细介绍
树在通过左旋右旋以后,树的搜索性质保持不变,但树的红黑性质则被破坏了,因此,红黑树插入和删除数据后,须要利用旋转与颜色重涂来从新恢复树的红黑性质。
3、红黑树的插入
要真正理解红黑树的插入,还得先理解二叉查找树的插入。磨刀不误砍柴工,我们再来了解一下二叉查找树的插入和红黑树的插入。
若是要在二叉查找树中插入一个结点,首先要查找到结点要插入的位置,而后进行插入。假设插入的结点为z的话,插入的伪代码以下:
1 TREE-INSERT(T, z) 2 y ← NIL 3 x ←T.root 4 while x ≠ NIL 5 do y ← x 6 if z.key < x.key 7 then x ← x.left 8 else x ← x.right 9 z.p ← y 10 if y == NIL 11 then T.root ← z 12 else if z.key < y.key 13 then y.left ← z 14 else y.right ← z