数据结构:红黑树插入与删除
看了很多文章写红黑树的插入与删除,发现大部分都是从算法导论上抄下来或者加以补充,不易新手学习,无意中看到了
维基上总结的红黑树,细看了下,还是觉得维基比较给力,代码简略易懂。特转做笔记收藏。。
1、性质
红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
性质1. 节点是红色或黑色。
性质2. 根是黑色。
性质3. 所有叶子都是黑色(叶子是NIL节点)。
性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
上述五个性质可以保证红黑树是一个高度平衡树。查找时间为O(lgn).
2、维基C代码实现:
父节点及叔父节点:
node grandparent(node n) { return n->parent->parent; } node uncle(node n) { if (n->parent == grandparent(n)->left) return grandparent(n)->right; else return grandparent(n)->left; }
情形1: 新节点N位于树的根上,没有父节点。
void insert_case1(node n) { if (n->parent == NULL) n->color = BLACK; else insert_case2(n); }
情形2: 新节点的父节点P是黑色。
void insert_case2(node n) { if (n->parent->color == BLACK) return; /* 树仍旧有效 */ else insert_case3(n); }
情形3: 如果父节点P和叔父节点U二者都是红色。P和U都变为黑,祖父节点变为红色并作为新插入节点对待。 |
void insert_case3(node n) { if (uncle(n) != NULL && uncle(n)->color == RED) { n->parent->color = BLACK; uncle(n)->color = BLACK; grandparent(n)->color = RED; insert_case1(grandparent(n)); } else insert_case4(n); }
情形4: 父节点P是红色而叔父节点U是黑色,并且新节点N是其父节点P的右子节点而父节点P又是其父节点的左子节点。在这种情形下,进行一次左旋转。 |
void insert_case4(node n) { if (n == n->parent->right && n->parent == grandparent(n)->left) { rotate_left(n->parent); n = n->left; } else if (n == n->parent->left && n->parent == grandparent(n)->right) { rotate_right(n->parent); n = n->right; } insert_case5(n); }
情形5: 父节点P是红色而叔父节点U 是黑色或缺少,新节点N 是其父节点的左子节点,而父节点P又是其父节点G的左子节点。在这种情形下,父节点变黑,祖父节点变红色,针对祖父节点G 进行一次右旋转。 |
void insert_case5(node n) { n->parent->color = BLACK; grandparent(n)->color = RED; if (n == n->parent->left && n->parent == grandparent(n)->left) { rotate_right(grandparent(n)); } else { /* Here, n == n->parent->right && n->parent == grandparent(n)->right */ rotate_left(grandparent(n)); } }