1.特性
- 每个节点或者是黑色,或者是红色。
- 根节点是黑色。
- 每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
- 如果一个节点是红色的,则它的子节点必须是黑色的。
- 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
注意:
- 特性(3)中的叶子节点,是指为空(NIL或null)的节点。
- 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。
2.应用
主要是用它来存储有序的数据,它的时间复杂度是O(lgn),效率非常之高。
3.基本操作
3.1 左旋
对x进行左旋,意味着"将x变成一个左节点"。
举例:
3.2 右旋
对Y进行左旋,意味着"将Y从一个右节点变成一个根节点"。
举例:
3.3 对比
它们是对称的。
3.4 添加
第一步: 将红黑树当作一颗二叉查找树,将节点插入。
- 红黑树本身就是一颗二叉查找树,将节点插入后,该树仍然是一颗二叉查找树。
- 此外,无论是左旋还是右旋,若旋转之前这棵树是二叉查找树,旋转之后它一定还是二叉查找树。这也就意味着,任何的旋转和重新着色操作,都不会改变它仍然是一颗二叉查找树的事实。
第二步:将插入的节点着色为"红色"。
- 将插入的节点着色为红色,不会违背"特性(5)"!
- 少违背一条特性,就意味着我们需要处理的情况越少。
- 接下来,就要努力的让这棵树满足其它性质即可;满足了的话,它就又是一颗红黑树了。
第三步: 通过一系列的旋转或着色等操作,使之重新成为一颗红黑树。
- 第二步中,将插入节点着色为"红色"之后,不会违背"特性(5)"。那它到底会违背哪些特性呢?
- 对于"特性(1)",显然不会违背了。因为我们已经将它涂成红色了。
- 对于"特性(2)",显然也不会违背。在第一步中,我们是将红黑树当作二叉查找树,然后执行的插入操作。而根据二叉查找数的特点,插入操作不会改变根节点。所以,根节点仍然是黑色。
- 对于"特性(3)",显然不会违背了。这里的叶子节点是指的空叶子节点,插入非空节点并不会对它们造成影响。
- 对于"特性(4)",是有可能违背的!
- 那接下来,想办法使之"满足特性(4)",就可以将树重新构造成红黑树了。
4. 为什么在STL的实现中用的是红黑树而不是其他树
红黑树和平衡二叉树区别如下:
- 红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单。
- 平衡二叉树追求绝对平衡,条件比较苛刻,实现起来比较麻烦,每次插入新节点之后需要旋转的次数不能预知。
平衡二叉树又被称为AVL树(有别于AVL算法),且具有以下性质:
- 它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
构造与调整方法:
- 平衡二叉树的常用算法有红黑树、AVL、Treap等。
- 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。