1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”。
红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。
它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
红黑树的五个性质:
1)每个结点要么是红的,要么是黑的。2)根结点是黑的。
3)每个叶结点,即空结点(NIL)是黑的。
4)如果一个结点是红的,那么它的俩个儿子都是黑的。
5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点
树的插入删除,会影响树的特性
红黑树操作:
插入节点为红色N,被插入的节点为P,P的父节点为G,P的叔叔节点为U
树的插入删除,会影响树的特性
插入:
1.插入节点的父亲节点为黑色,不会影响树的性能。所以不用改变。
2.插入节点的父亲节点为红色,会分成3中情况:
a)叔叔节点为红色。
无论N在P左右,P在G的左右。把G换成红色,把P、U换成黑色。然后把G当成插入点向上验证树的特性。
b)叔叔节点为黑色或者没有。
所有情况如下图
发生下面情况发生变色右旋(G变红,P变成红色)
发生下面情况发生变色左旋(G变红,P变成红色)
发生下面情况发生右旋和变色左旋情况
发生下面情况发生左旋和变色右旋情况.第二个图形中PN位置反了
删除:
1.删除节点没有子节点,直接删除。
2.删除节点有子节点。
a)删除节点的孩子节点是单支节点(没有孩子节点),或者前继(节点左边最大的节点)后继(节点右边最小的节点)为单节点。直接替换与换颜色,移除删除的。如下:R为要删除的节点,M是R右边最小值。
b)R为要删除的节点,M是R右边最小值。N是M的右节点。R与M位置与颜色互换。N替换R。
如果发生b)种情况。N的位置变化会影响红黑树的特性。
U节点为红色:
U、UL、UR都为黑色:
U、UR为黑,UL为红:
U为黑色、UR为红色:
jdk1.8 HashMap.TreeNode的部分代码详解
//排序新插入的数据 并返回root节点
static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,
TreeNode<K,V> x) {//x为新插入的treenode
x.red = true;//默认设置成[红]
for (TreeNode<K,V> xp, xpp, xppl, xppr;;) {
if ((xp = x.parent) == null) {//x的父节点为xp,如果xp为空,那么xp就是root,因为红黑树中只有root节点的父节点为null
x.red = false;
return x;
}
else if (!xp.red || (xpp = xp.parent) == null)//xp为黑,不影响树的特征,直接插入。
//x的祖父节点为null,xp为root,树高为1不影响性能。
return root;
if (xp == (xppl = xpp.left)) {//在祖父节点左边的树。
if ((xppr = xpp.right) != null && xppr.red) {//父亲节点右边节点为红色。
xppr.red = false;
xp.red = false;
xpp.red = true;
x = xpp;//检查祖父接单是否符合树的特性。进行下一次循环。
}
else {//祖父节点右边节点为黑色或没有
if (x == xp.right) {//插入节点在父节点的右边
root = rotateLeft(root, x = xp);//左旋转,
xpp = (xp = x.parent) == null ? null : xp.parent;//x为旋转后的子节点(原父亲节点),xp
//x为旋转后的父节点(原子亲节点)
}
if (xp != null) {
xp.red = false;//xp(原插入节点)设成黑
if (xpp != null) {
xpp.red = true;
root = rotateRight(root, xpp);//右旋
}
}
}
}
else {//在祖父节点右边的树。
if (xppl != null && xppl.red) {//父亲节点右边节点为红色。
xppl.red = false;
xp.red = false;
xpp.red = true;
x = xpp;//检查祖父接单是否符合树的特性。进行下一次循环。
}
else {
if (x == xp.left) {
root = rotateRight(root, x = xp);
xpp = (xp = x.parent) == null ? null : xp.parent;
}
if (xp != null) {
xp.red = false;
if (xpp != null) {
xpp.red = true;
root = rotateLeft(root, xpp);
}
}
}
}
}
}
//删除treeNode后 ,发生位置变化的节点,触发的tree 的排序
static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
TreeNode<K,V> x) {
for (TreeNode<K,V> xp, xpl, xpr;;) {
if (x == null || x == root)
return root;
else if ((xp = x.parent) == null) {
x.red = false;
return x;
}
else if (x.red) {
x.red = false;
return root;
}
else if ((xpl = xp.left) == x) {//x是P的左节点
if ((xpr = xp.right) != null && xpr.red) {//兄弟节点为 红
xpr.red = false;
xp.red = true;
root = rotateLeft(root, xp);
xpr = (xp = x.parent) == null ? null : xp.right;
}
if (xpr == null)
x = xp;
else {
TreeNode<K,V> sl = xpr.left, sr = xpr.right;
if ((sr == null || !sr.red) &&
(sl == null || !sl.red)) { //xpr的孩子节点非红
xpr.red = true;
x = xp;
}
else {//xpr的孩子节点至少有一个为红
if (sr == null || !sr.red) {//xpr的右孩子节点非红,那么左孩子节点一定是红
if (sl != null)
sl.red = false;
xpr.red = true;
root = rotateRight(root, xpr);
xpr = (xp = x.parent) == null ?
null : xp.right;
}
if (xpr != null) {
xpr.red = (xp == null) ? false : xp.red;
if ((sr = xpr.right) != null)
sr.red = false;
}
if (xp != null) {
xp.red = false;
root = rotateLeft(root, xp);
}
x = root;
}
}
}
else { // x是P的右节点。操作顺序相反
if (xpl != null && xpl.red) {
xpl.red = false;
xp.red = true;
root = rotateRight(root, xp);
xpl = (xp = x.parent) == null ? null : xp.left;
}
if (xpl == null)
x = xp;
else {
TreeNode<K,V> sl = xpl.left, sr = xpl.right;
if ((sl == null || !sl.red) &&
(sr == null || !sr.red)) {
xpl.red = true;
x = xp;
}
else {
if (sl == null || !sl.red) {
if (sr != null)
sr.red = false;
xpl.red = true;
root = rotateLeft(root, xpl);
xpl = (xp = x.parent) == null ?
null : xp.left;
}
if (xpl != null) {
xpl.red = (xp == null) ? false : xp.red;
if ((sl = xpl.left) != null)
sl.red = false;
}
if (xp != null) {
xp.red = false;
root = rotateRight(root, xp);
}
x = root;
}
}
}
}
}