diff --git a/BinaryTree/BalanceTree/Red-Black Tree/RBTree.h b/BinaryTree/BalanceTree/Red-Black Tree/RBTree.h new file mode 100644 index 0000000..0d0b587 --- /dev/null +++ b/BinaryTree/BalanceTree/Red-Black Tree/RBTree.h @@ -0,0 +1,370 @@ +#pragma once +#include +#include "TreeNode.h" +template +class RBTree { +private: + TreeNode* root; + TreeNode* nul; + int size; + + void initNul() { + nul = new TreeNode(0, nul, nul, nul); + nul->color = Color::RED; + } + void inorder(TreeNode* x); + void dispose(TreeNode* x) { + if (x == nullptr || x == nul) return; + dispose(x->left); + dispose(x->right); + delete x; + //重点不能delete nul(作为全局的哨兵) + } +public: + RBTree() : size(0) { initNul(); root = nul; } + RBTree(TreeNode* r, int s) : root(r), size(s) { initNul(); } + ~RBTree() { + dispose(root); + root = nullptr; + delete nul; + //删除哨兵,需要删除 + } + + TreeNode* RotateLeft(TreeNode* x);//RR + TreeNode* RotateRight(TreeNode* x);//LL + + + void insert(const T& e); + void fixinsert(TreeNode* x); + void fixdelete(TreeNode* x); + void inorder() { inorder(root); } + void erase(const T& e); + TreeNode* find(const T& e); +}; + +template +inline TreeNode* RBTree::RotateLeft(TreeNode* x) { + TreeNode* y = x->right; // 右孩子 + TreeNode* T2 = y->left; // y 的左子树暂存 + + // 左旋 + y->left = x; + x->right = T2; + + // 更新 parent 指针 + if (T2) T2->parent = x; // 如果 T2 存在 + y->parent = x->parent; // y 接上 x 的父节点 + + if (x->parent == nul) { // x 是根节点 + root = y; + } + else if (x == x->parent->left) { + x->parent->left = y; + } + else { + x->parent->right = y; + } + + x->parent = y; + + return y; // 返回新子树根 +} + + +template +TreeNode* RBTree::RotateRight(TreeNode* x) { + //有parent,不需要递归,直接修改parent + TreeNode* y = x->left; + TreeNode* T2 = y->right; + + // 旋转 + y->right = x; + x->left = T2; + + // 更新 parent 指针 + if (T2) T2->parent = x; // 如果 T2 存在 + y->parent = x->parent; // y 接上 x 的父节点 + + if (x->parent == nul) { // x 是根节点 + root = y; + } + else if (x == x->parent->left) { + x->parent->left = y; + } + else { + x->parent->right = y; + } + x->parent = y; + return y; // 返回新子树根 +} + + +template +inline void RBTree::inorder(TreeNode* x) +{ + if (x == nul) return; + inorder(x->left); + std::cout << x->element << " "; + inorder(x->right); +} + +template +inline void RBTree::insert(const T& e) +{ + TreeNode* p = new TreeNode(e, nul, nul, nul); + + TreeNode* current = root; + TreeNode* parent = nul; + //BST插入,有parent就不需要递归节点了 + while (current != nul) { + parent = current; + if (e < parent->element) current = parent->left; + else current = parent->right; + } + + p->parent = parent; + if (parent == nul) root = p; + if (parent == nul) root = p; + else if (e < parent->element) parent->left = p; + else parent->right = p; + + //FixInsert + fixinsert(p); +} + +template +inline void RBTree::fixinsert(TreeNode* x) +{ + while (x != root && x->parent->color == Color::RED) { + //看叔叔 + if (x->parent->parent->left == x->parent) { + //左节点 + if (x->parent->parent->right->color == Color::RED) { + //叔叔红 + x->parent->color = x->parent->parent->right->color = Color::BLACK; + x->parent->parent->color = Color::RED; + //fixinsert(x->parent->parent);递归不好,容易重复判断,不易处理根节点颜色 + x = x->parent->parent; + continue; + } + if (x == x->parent->left) { + //LL//先变色祖父,父亲 + x->parent->parent->color = Color::RED; + x->parent->color = Color::BLACK; + //再右旋 + RotateRight(x->parent->parent); + } + //LR + if (x == x->parent->right) { + //变成LL + x = x->parent; + RotateLeft(x); + //不需要再LL了,下一个循环自动变成LL + } + } + //else对称情况,父亲为右节点 + else { + //1-叔叔红 + if (x->parent->parent->left->color == Color::RED) { + x->parent->parent->left->color = Color::BLACK; + x->parent->color = Color::BLACK; + x->parent->parent->color = Color::RED; + x = x->parent->parent; + } + //2-叔叔黑 + else { + //2-1-RL -> 调整为RR,再做下一步操作 + if (x == x->parent->left) { + x = x->parent; + RotateRight(x); + } + + //3-RR,接着上面的2-1 + x->parent->color = Color::BLACK; + x->parent->parent->color = Color::RED; + RotateLeft(x->parent->parent); + } + } + } + root->color = Color::BLACK; +} +// x 表示被删除节点的替代节点(可能是 nul 哨兵) +// 只有当被删节点或替代节点是黑色时,才需要进入 fixdelete +template +void RBTree::fixdelete(TreeNode* x) { + while (x != root && x->color == Color::BLACK) { + // 情况1:x 是左孩子 + if (x == x->parent->left) { + TreeNode* w = x->parent->right; // x 的兄弟节点 + + // case 1: 兄弟是红色 + // -> 把兄弟染黑,父亲染红,然后左旋 + // -> 转化为兄弟是黑色的情况 + if (w->color == Color::RED) { + w->color = Color::BLACK; + x->parent->color = Color::RED; + RotateLeft(x->parent); + w = x->parent->right; // 更新兄弟 + } + + // case 2: 兄弟是黑色,并且两个侄子(w->left, w->right)都是黑色 + // -> 把兄弟染红,相当于把 "多余的黑色" 往上传递 + // -> 修复过程继续向上进行 + if (w->left->color == Color::BLACK && w->right->color == Color::BLACK) { + w->color = Color::RED; + x = x->parent; // 往上修复 + } + else { + // case 3: 兄弟是黑色,且兄弟的右孩子是黑色,左孩子是红色 + // -> 先把兄弟染红,左孩子染黑,然后右旋兄弟 + // -> 转化为 case 4 + if (w->right->color == Color::BLACK) { + w->left->color = Color::BLACK; + w->color = Color::RED; + RotateRight(w); + w = x->parent->right; // 更新兄弟 + } + + // case 4: 兄弟是黑色,且兄弟的右孩子是红色 + // -> 用兄弟替换父亲颜色,父亲染黑,兄弟的右孩子染黑 + // -> 左旋父亲,修复完成,直接退出循环 + w->color = x->parent->color; + x->parent->color = Color::BLACK; + w->right->color = Color::BLACK; + RotateLeft(x->parent); + x = root; // 结束循环 + } + } + // 情况2:x 是右孩子(对称情况) + else { + TreeNode* w = x->parent->left; + + if (w->color == Color::RED) { + w->color = Color::BLACK; + x->parent->color = Color::RED; + RotateRight(x->parent); + w = x->parent->left; + } + + if (w->right->color == Color::BLACK && w->left->color == Color::BLACK) { + w->color = Color::RED; + x = x->parent; + } + else { + if (w->left->color == Color::BLACK) { + w->right->color = Color::BLACK; + w->color = Color::RED; + RotateLeft(w); + w = x->parent->left; + } + + w->color = x->parent->color; + x->parent->color = Color::BLACK; + w->left->color = Color::BLACK; + RotateRight(x->parent); + x = root; + } + } + } + + // 最后保证 x 是黑色(可能是根或者 nul) + x->color = Color::BLACK; +} + +template +inline void RBTree::erase(const T& e) +{ + TreeNode* z = find(e); + //1-BST删除重置,找本节点右树最小或者左树最大 + TreeNode* y = z; // 实际要删除的节点(可能是 z,也可能是 z 的后继) + TreeNode* x; // y 的替代节点(可能是子节点,也可能是 nul) + Color yOriginalColor = y->color; // 记录 y 的原始颜色,决定是否需要 fixdelete + // case 1: z 没有左子树 -> 用右子树替代 z + if (z->left == nul) { + x = z->right; // 替代节点 + // 把 z 从父亲断开 + if (z->parent == nul) root = x; + else if (z == z->parent->left) z->parent->left = x; + else z->parent->right = x; + x->parent = z->parent; + } + // case 2: z 没有右子树 -> 用左子树替代 z + else if (z->right == nul) { + x = z->left; + if (z->parent == nul) root = x; + else if (z == z->parent->left) z->parent->left = x; + else z->parent->right = x; + x->parent = z->parent; + } + // case 3: z 左右孩子都有 -> 找到 z 的中序后继 + else { + // 找 z 的后继(右子树最左节点) + y = z->right; + while (y->left != nul) y = y->left; + yOriginalColor = y->color; // 记录后继的颜色 + x = (y->right != nul ? y->right : nul); // 后继的右孩子作为替代 + + // 如果 y 不是 z 的直接右孩子 + if (y->parent != z) { + // 把 y->right 替代 y + if (y->parent->left == y) y->parent->left = x; + else y->parent->right = x; + x->parent = y->parent; + + // 把 z->right 挂到 y 的右子树 + y->right = z->right; + y->right->parent = y; + } + + // 把 z->left 挂到 y 的左子树 + if (z->parent == nul) root = y; + else if (z == z->parent->left) z->parent->left = y; + else z->parent->right = y; + y->parent = z->parent; + + y->left = z->left; + y->left->parent = y; + y->color = z->color; + } + delete z; + + //2-RBT性质重置 + // 如果删除的实际节点是黑色,可能破坏红黑树性质 → fixdelete + if (yOriginalColor == Color::BLACK) { + fixdelete(x); + } + +} +template +inline TreeNode* RBTree::find(const T& e) +{ + TreeNode* p = root; + while (p != nul) { + if (e < p->element) p = p->left; + else if (e > p->element) p = p->right; + else break; + } + if (!p) p = nul; + return p; +} +/* +推荐写法 +if (x->parent == x->parent->parent->left) { // 父在左 + TreeNode* y = x->parent->parent->right; // 叔叔 + if (y->color == Color::RED) { // Case 1: 叔红 + x->parent->color = Color::BLACK; + y->color = Color::BLACK; + x->parent->parent->color = Color::RED; + x = x->parent->parent; // 上移祖父 + } else { + if (x == x->parent->right) { // Case 2: LR + x = x->parent; + RotateLeft(x); + } + // Case 3: LL + x->parent->color = Color::BLACK; + x->parent->parent->color = Color::RED; + RotateRight(x->parent->parent); + } +按照顺序写,这里可以看else(父亲为右节点)的思路 +*/ diff --git a/BinaryTree/BalanceTree/Red-Black Tree/README.MD b/BinaryTree/BalanceTree/Red-Black Tree/README.MD new file mode 100644 index 0000000..a36e8e2 --- /dev/null +++ b/BinaryTree/BalanceTree/Red-Black Tree/README.MD @@ -0,0 +1,263 @@ +[TOC] +## 绾㈤粦鏍戞彃鍏ユ濊矾 +濂界殑锛屾垜浠妸 **绾㈤粦鏍戞彃鍏ョ殑瀹屾暣閫昏緫**鏁寸悊涓涓嬶紝鍒嗘楠ゃ佸垎鎯呭喌璁诧紝淇濊瘉娓呮櫚鏄撴噦锛 + +--- + +## 馃敼 绾㈤粦鏍戞彃鍏ラ昏緫 + +### 1锔忊儯 鍩烘湰姝ラ + +1. **鏅 BST 鎻掑叆** + + * 鎸変簩鍙夋悳绱㈡爲鐨勮鍒欙紝鎶婃柊鑺傜偣 `x` 鎻掑叆鍒板悎閫備綅缃 + * 鏂拌妭鐐瑰垵濮嬪寲涓 **绾㈣壊**锛堝洜涓烘彃鍏ョ孩鑹茶妭鐐规洿瀹规槗缁存寔榛戦珮锛夈 + +2. **鍒ゆ柇鏄惁闇瑕佷慨澶** +``` cpp +鎻掑叆鏂拌妭鐐 z (绾㈣壊) +| ++-- 鐖舵槸榛戣壊 鈫 OK锛岀洿鎺ユ彃鍏 +| ++-- 鐖舵槸绾㈣壊 + | + +-- 鍙斿彅鏄孩鑹 鈫 鐖堕粦鍙旈粦锛岀绾紝涓婄Щ鍒扮鐖讹紝缁х画妫鏌 + | + +-- 鍙斿彅鏄粦鑹 + | + +-- z 鍦ㄧ埗鐨勫悓鍚戯紙宸﹀乏鎴栧彸鍙筹級 鈫 Case 3锛屾棆杞 + 棰滆壊浜ゆ崲 + +-- z 鍦ㄧ埗鐨勫紓鍚戯紙宸﹀彸鎴栧彸宸︼級 鈫 Case 2锛屽厛鏃嬭浆鐖讹紝鍐嶅彉涓哄悓鍚戯紝缁х画 Case 3 +``` + * 濡傛灉鐖惰妭鐐规槸榛戣壊 鈫 绾㈤粦鎬ц川涓嶇牬鍧忥紝涓嶉渶瑕 fix銆 + * 濡傛灉鐖惰妭鐐规槸绾㈣壊 鈫 杩濆弽鈥滅孩鑹茶妭鐐逛笉鑳芥湁绾㈣壊瀛愯妭鐐光濓紝闇瑕佷慨澶嶃 + * 鑰冭檻鍙斿彅鏄笉鏄孩鐨 + * ->鍙斿彅鏄孩鐨勫氨 涓璧峰彉榛戯紝绁栫埗鍙樼孩 + * ->鍙斿彅涓嶆槸绾㈢殑锛岃冭檻鏃嬭浆+鍙樿壊 + +--- + +### 2锔忊儯 fixinsert 淇閫昏緫 + +璁撅細 + +* `x` = 褰撳墠鎻掑叆鑺傜偣 +* `p` = 鐖惰妭鐐 +* `u` = 鍙斿彅鑺傜偣锛堢埗鑺傜偣鐨勫厔寮燂級 +* `g` = 绁栫埗鑺傜偣 + +#### **鎯呭喌 1锛氬彅鍙旇妭鐐规槸绾㈣壊** + +* **鏉′欢**锛歚p` 鏄孩鑹诧紝`u` 鏄孩鑹 +* **澶勭悊**锛 + + 1. 鐖惰妭鐐 `p` 鏌撻粦 + 2. 鍙斿彅鑺傜偣 `u` 鏌撻粦 + 3. 绁栫埗鑺傜偣 `g` 鏌撶孩 + 4. 灏 `x` 涓婄Щ鍒扮鐖惰妭鐐 `g`锛岀户缁惊鐜垽鏂 +* **鍘熷洜**锛氶氳繃閲嶆柊鏌撹壊锛屾妸绾㈢孩鍐茬獊涓婄Щ锛屼繚鎸侀粦楂樹笉鍙 + +--- + +#### **鎯呭喌 2锛氬彅鍙旇妭鐐规槸榛戣壊** + +* **鏉′欢**锛歚p` 鏄孩鑹诧紝`u` 鏄粦鑹 +* **瀛愭儏鍐**锛堟牴鎹 `x` 鍦ㄧ埗鑺傜偣鐨勫乏鍙充綅缃級锛 + +1. **宸-宸︼紙LL锛** + + * `x` 鏄 `p` 鐨勫乏瀛╁瓙锛宍p` 鏄 `g` 鐨勫乏瀛╁瓙 + * **澶勭悊**锛 + + 1. 鐖惰妭鐐规煋榛戯紝绁栫埗鏌撶孩 + 2. 鍙虫棆绁栫埗 + +2. **宸-鍙筹紙LR锛** + + * `x` 鏄 `p` 鐨勫彸瀛╁瓙锛宍p` 鏄 `g` 鐨勫乏瀛╁瓙 + * **澶勭悊**锛 + + 1. 宸︽棆鐖惰妭鐐癸紙灏 LR 杞寲涓 LL锛 + 2. 鍐嶆墽琛 LL 鎯呭喌鐨勫彸鏃 + 鏌撹壊 + +3. **鍙-鍙筹紙RR锛** + + * 瀵圭О LL锛氬彸瀛╁瓙鐨勫彸瀛╁瓙鎻掑叆 + * 宸︽棆绁栫埗 + 璋冩暣棰滆壊 + +4. **鍙-宸︼紙RL锛** + + * 瀵圭О LR锛氬彸瀛╁瓙鐨勫乏瀛╁瓙鎻掑叆 + * 鍙虫棆鐖惰妭鐐 鈫 鍙樻垚 RR 鈫 宸︽棆绁栫埗 + 璋冩暣棰滆壊 + +--- + +### 3锔忊儯 寰幆缁堟 + +* 褰撶埗鑺傜偣鏄粦鑹诧紝鎴栬呭埌杈炬牴鑺傜偣锛屽惊鐜粨鏉 +* 鏈鍚 **鏍硅妭鐐瑰繀椤绘煋榛** + +--- + +### 馃敼 鎬荤粨鍏抽敭鐐 + +1. **鏂拌妭鐐圭孩鑹** 鈫 淇濇寔榛戦珮涓嶅彉 +2. **绾㈢孩鍐茬獊** 鈫 鏍规嵁鍙斿彅棰滆壊鍒嗕袱绫诲鐞嗭細 + + * 绾㈣壊鍙斿彅 鈫 涓婄Щ鏌撹壊 + * 榛戣壊鍙斿彅 鈫 鏃嬭浆 + 鏌撹壊 +3. **鏃嬭浆 + 鏌撹壊** 鈫 鍙敼鍙樺眬閮ㄧ粨鏋勶紝淇濇寔鏁翠綋 BST 鍜岀孩榛戞ц川 +4. **鏍硅妭鐐逛繚鎸侀粦鑹** 鈫 淇濊瘉鏍戠殑榛戦珮涓鑷 + +--- + +濡傛灉浣犻渶瑕侊紝鎴戝彲浠ュ府浣犵敾涓寮 **绾㈤粦鏍戞彃鍏ョず鎰忓浘**锛屾妸 LL/LR/RR/RL 鍥涚鏃嬭浆鍦烘櫙鍜岄鑹插彉鍖栧彲瑙嗗寲锛岀湅璧锋潵闈炲父鐩磋銆 + +浣犳兂璁╂垜鐢诲悧锛 + + +## 绾㈤粦鏍戝垹闄ゆ濊矾 +濂斤紝鎴戠粰浣犳⒊鐞嗕竴涓 **绾㈤粦鏍戝垹闄ょ殑鏁翠綋鎬濊矾**锛屽彧璁查昏緫锛屼笉璐翠唬鐮侊細 + +--- + +### 1锔忊儯 鎵惧埌瑕佸垹闄ょ殑鑺傜偣 + +* 棣栧厛鎸夌収鏅氫簩鍙夋悳绱㈡爲锛圔ST锛夋煡鎵惧緟鍒犻櫎鑺傜偣 `z`銆 +* 濡傛灉鑺傜偣涓嶅瓨鍦紝灏辩粨鏉熴 + +--- + +### 2锔忊儯 鍒嗘儏鍐靛鐞嗚妭鐐 + +绾㈤粦鏍戝垹闄よ窡 BST 鍒犻櫎绫讳技锛屽垎涓夌鎯呭喌锛 + +1. **鑺傜偣娌℃湁瀛愯妭鐐癸紙鍙跺瓙锛** + + * 鐩存帴鎶婂畠浠庣埗鑺傜偣鏂紑銆 + * 濡傛灉鑺傜偣鏄粦鑹诧紝鍒犻櫎浼氱牬鍧忛粦楂橈紝闇瑕佷慨澶嶃 + +2. **鑺傜偣鍙湁涓涓瀛** + + * 鐢ㄥ敮涓鐨勫瀛愭浛浠h鑺傜偣鎸傚埌鐖惰妭鐐逛笂銆 + * 濡傛灉鍒犻櫎鐨勬槸榛戣壊鑺傜偣锛屼篃鍙兘鐮村潖绾㈤粦鎬ц川锛岄渶瑕佷慨澶嶃 + +3. **鑺傜偣鏈変袱涓瀛** + + * 鎵捐鑺傜偣鐨 **涓簭鍚庣户**锛堝彸瀛愭爲鏈宸︾殑鑺傜偣锛夋浛浠e畠銆 + * 鍒犻櫎鍚庣户鑺傜偣锛堝悗缁ф渶澶氭湁涓涓彸瀛╁瓙锛夛紝杩欎竴姝ラ鍖栦负鎯呭喌 1 鎴 2銆 + * 鐒跺悗鎶婅鍒犻櫎鑺傜偣鐨勫乏鍙冲瀛愭帴鍒板悗缁т笂锛岀户鎵块鑹层 + * 濡傛灉鍚庣户鍘熸湰鏄粦鑹诧紝涔熼渶瑕佷慨澶嶃 + +--- + +### 3锔忊儯 淇绾㈤粦鏍戞ц川 + +* 鍒犻櫎榛戣壊鑺傜偣鎴栫敤榛戣壊鑺傜偣鏇夸唬鏃讹紝浼氱牬鍧 **榛戦珮** 鎴 **绾㈤粦鎬ц川**銆 +* 淇鏍稿績鎬濊矾锛 + + 1. **鍏勫紵鑺傜偣绾㈣壊** 鈫 鏃嬭浆骞惰皟鏁撮鑹诧紝浣垮厔寮熷彉榛戙 + 2. **鍏勫紵榛戣壊锛屽厔寮熺殑瀛╁瓙閮芥槸榛戣壊** 鈫 鍏勫紵鏌撶孩锛屾妸鈥滃弻閲嶉粦鈥濆悜涓婁紶閫掋 + 3. **鍏勫紵榛戣壊锛屾湁绾㈣壊渚勫瓙** 鈫 鏃嬭浆 + 鏌撹壊锛岀洿鎺ユ秷闄ゅ弻閲嶉粦銆 +* 淇寰幆涓鐩存墽琛岋紝鐩村埌鍙岄噸榛戞秷闄ゆ垨鑰呭埌杈炬牴鑺傜偣銆 + +--- + +### 4锔忊儯 鐗瑰埆娉ㄦ剰 + +* 鏍硅妭鐐瑰缁堣淇濇寔榛戣壊銆 +* 鍒犻櫎杩囩▼灏介噺浣跨敤 **鍝ㄥ叺鑺傜偣 `nul`** 鏇夸唬绌烘寚閽堬紝閬垮厤姣忔鍒ゆ柇 `nullptr`銆 +* 鍒犻櫎閫昏緫涓昏鏄 **BST 鏇挎崲 + fixdelete 淇** 涓ゆ缁撳悎銆 + +--- + +绠鍗曟荤粨涓鍙ヨ瘽灏辨槸锛 + +**鈥滃厛鎸 BST 鍒犻櫎鑺傜偣锛屽啀鏍规嵁琚垹鑺傜偣棰滆壊鍐冲畾鏄惁淇锛岀敤鏃嬭浆鍜屾煋鑹插鐞嗗弻閲嶉粦銆傗** + +濂斤紝鎴戜滑鎶 **绾㈤粦鏍戝垹闄ゅ悗淇鐨勬牳蹇冩楠**缁嗗寲璁茶В涓涓嬶紝鎶婃瘡绉嶆儏鍐电殑閫昏緫鍜屽師鍥犻兘鎷嗗紑鐪嬨傚亣璁惧垹闄ゅ悗鍑虹幇鐨勮妭鐐 `x` 甯︽湁 **鈥滃弻閲嶉粦鈥濓紙double black锛**锛岃繖鏄慨澶嶇殑瑙﹀彂鏉′欢銆 + +--- + +## 馃敼 淇绾㈤粦鏍戞ц川锛圖ouble Black 澶勭悊锛 + +### 鎯呮櫙姒傚康 + +* 鍒犻櫎鎴栨浛浠h妭鐐规槸榛戣壊 鈫 鐮村潖浜嗙孩榛戞爲鐨勯粦楂樸 +* 鎴戜滑鐢 `x` 琛ㄧず鏇夸唬鑺傜偣锛堝彲鑳芥槸鍝ㄥ叺 `nul`锛夈 +* `w` 琛ㄧず `x` 鐨勫厔寮熻妭鐐广 + +--- + +### **鎯呭喌 1锛氬厔寮熻妭鐐圭孩鑹** + +**鏉′欢**锛歚w->color == RED` + +**澶勭悊閫昏緫**锛 + +1. 鎶婂厔寮熸煋榛戯紝鐖惰妭鐐规煋绾€ +2. 瀵圭埗鑺傜偣鍋氭棆杞紙宸︽棆鎴栧彸鏃嬶紝瑙 x 鍦ㄥ乏杩樻槸鍙筹級銆 +3. 杞崲鎴愨滃厔寮熸槸榛戣壊鈥濈殑鎯呭喌锛岃繘鍏ヤ笅涓杞惊鐜鐞嗐 + +**鍘熷洜**锛 + +* 绾㈣壊鍏勫紵鎰忓懗鐫鐖惰妭鐐瑰繀鐒舵槸榛戣壊锛堢孩榛戞ц川锛夛紝鏃嬭浆鍚庡彲浠ヨ榛戦珮骞宠 锛屽悓鏃舵妸闂杞寲涓烘洿瀹规槗澶勭悊鐨勫厔寮熼粦鑹叉儏鍐点 + +--- + +### **鎯呭喌 2锛氬厔寮熸槸榛戣壊涓斿厔寮熶袱涓瀛愰兘鏄粦鑹** + +**鏉′欢**锛歚w->color == BLACK && w->left->color == BLACK && w->right->color == BLACK` + +**澶勭悊閫昏緫**锛 + +1. 鎶婂厔寮熸煋绾€ +2. 鎶 x 鐨勫弻閲嶉粦鍚戠埗鑺傜偣浼犻掞細`x = x->parent`锛屽惊鐜户缁 + +**鍘熷洜**锛 + +* 榛戦珮鍑忓皯鍙戠敓鍦 x 鎵鍦ㄧ殑璺緞涓娿 +* 鍏勫紵鐨勪袱涓瓙鑺傜偣閮芥槸榛戣壊 鈫 榛戦珮娌℃硶琛ュ伩锛屽彧鑳芥妸澶氫綑鐨勯粦鑹测滃悜涓婇掑綊鈥濄 + +--- + +### **鎯呭喌 3锛氬厔寮熸槸榛戣壊涓旀湁绾㈣壊渚勫瓙** + +**鏉′欢**锛歚w->color == BLACK` 涓旇嚦灏戞湁涓涓瓙鑺傜偣绾㈣壊 + +**澶勭悊閫昏緫**锛 + +1. 濡傛灉 x 鏄乏瀛╁瓙锛 + + * case RL锛氬厛瀵瑰厔寮熷彸鏃嬶紝璁╃孩鑹蹭緞瀛愯浆鍒板彸渚с + * case RR锛氱埗浜插乏鏃嬶紝鍚屾椂璋冩暣鐖朵翰銆佸厔寮熷拰绾㈣壊渚勫瓙鐨勯鑹层 +2. 瀵圭О鍦帮紝濡傛灉 x 鏄彸瀛╁瓙锛 + + * case LR锛氬厛宸︽棆鍏勫紵 + * case LL锛氱埗浜插彸鏃 + 鏌撹壊 + +**鍘熷洜**锛 + +* 绾㈣壊渚勫瓙鍙互鈥滆ˉ鍋库濊鍒犻櫎榛戣壊鑺傜偣閫犳垚鐨勯粦楂樼己澶便 +* 閫氳繃鏃嬭浆鍜屾煋鑹诧紝鍙岄噸榛戠珛鍗虫秷闄わ紝绾㈤粦鏍戞ц川鎭㈠銆 + +--- + +### 馃敼 寰幆缁撴潫鏉′欢 + +* 鍙岄噸榛戞秷闄わ紙x 琚噸鏂版煋榛戞垨鑰呭埌杈炬牴鑺傜偣锛夈 +* 鏍硅妭鐐瑰繀椤讳繚鎸侀粦鑹 鈫 鏈鍚庡啀鏄惧紡璁剧疆 `root->color = BLACK`銆 + +--- + +馃挕 **鐩磋鐞嗚В**锛 + +1. **绾㈠厔寮** 鈫 杞寲闂 +2. **榛戝厔寮+榛戜緞瀛** 鈫 寰涓婇 +3. **榛戝厔寮+绾緞瀛** 鈫 琛ュ伩榛戦珮锛岀珛鍗宠В鍐 + +--- + +濡傛灉浣犳兂锛屾垜鍙互鐢讳竴寮 **鍒犻櫎淇娴佺▼鍥**锛岀敤鑺傜偣棰滆壊鏍囨敞姣忎竴姝ョ殑鏃嬭浆鍜屾煋鑹诧紝鐩磋灞曠ず涓夌鎯呭喌銆 + +浣犲笇鏈涙垜鐢诲悧锛 + diff --git a/BinaryTree/BalanceTree/Red-Black Tree/TreeNode.h b/BinaryTree/BalanceTree/Red-Black Tree/TreeNode.h new file mode 100644 index 0000000..f218d65 --- /dev/null +++ b/BinaryTree/BalanceTree/Red-Black Tree/TreeNode.h @@ -0,0 +1,16 @@ +#pragma once +enum Color { RED, BLACK }; + +template +class TreeNode { +public: + T element; + TreeNode* left; + TreeNode* right; + TreeNode* parent; + Color color; + + TreeNode() : left(nullptr), right(nullptr), parent(nullptr), color(Color::RED) {} + TreeNode(const T& e) : element(e), left(nullptr), right(nullptr), parent(nullptr), color(Color::RED) {} + TreeNode(const T& e, TreeNode* l, TreeNode* r, TreeNode* p) : element(e), left(l), right(r), parent(p), color(Color::RED) {} +}; \ No newline at end of file diff --git a/BinaryTree/BalanceTree/Red-Black Tree/main.cpp b/BinaryTree/BalanceTree/Red-Black Tree/main.cpp new file mode 100644 index 0000000..e7999ab --- /dev/null +++ b/BinaryTree/BalanceTree/Red-Black Tree/main.cpp @@ -0,0 +1,21 @@ +#include "RBTree.h" +using namespace std; +int main() { + RBTree t; + //一定关注NIL指针的使用,所有悬挂出的节点都要用NIL + t.insert(8); + t.insert(5); + t.insert(3); + t.insert(2); + t.insert(7); + t.insert(1); + t.inorder(); + cout << endl; + t.erase(7); + t.inorder(); + return 0; +} +/* +1 2 3 5 7 8 +1 2 3 5 8 +*/ \ No newline at end of file