From cf6af38144d09e3d9208223ea7fb2575038207d1 Mon Sep 17 00:00:00 2001 From: Shine wOng <1551885@tongji.edu.cn> Date: Sun, 23 Jun 2019 15:12:37 +0800 Subject: [PATCH] create Red-Black tree head file, not tested yet. --- thu_dsa/chp5/binNode.h | 9 +- thu_dsa/chp5/binTree.h | 4 +- thu_dsa/chp7/BST.h | 1 + thu_dsa/chp8/RedBlack.h | 179 +++++++++++++++++++++++++++++++++ thu_dsa/chp8/test_RedBlack.cpp | 0 5 files changed, 187 insertions(+), 6 deletions(-) create mode 100644 thu_dsa/chp8/RedBlack.h create mode 100644 thu_dsa/chp8/test_RedBlack.cpp diff --git a/thu_dsa/chp5/binNode.h b/thu_dsa/chp5/binNode.h index 0de3743..a3835fb 100644 --- a/thu_dsa/chp5/binNode.h +++ b/thu_dsa/chp5/binNode.h @@ -6,6 +6,8 @@ #define BinNodePosi(T) BinNode* +typedef enum{RED, BLACK} Color; + template class BinNode{ protected: @@ -18,15 +20,14 @@ public: BinNodePosi(T) parent; BinNodePosi(T) leftChild; BinNodePosi(T) rightChild; + Color color; T data; int height; - int color; int npl; //constructor - BinNode() : parent(nullptr), leftChild(nullptr), rightChild(nullptr), height(0), color(0), npl(0) {}; - BinNode(T const &val) : parent(nullptr), leftChild(nullptr), rightChild(nullptr), data(val), height(0), color(0), npl(0) {}; - BinNode(T const &val, BinNodePosi(T) p): parent(p), leftChild(nullptr), rightChild(nullptr), data(val), height(0), color(0), npl(0) {}; + BinNode() : parent(nullptr), leftChild(nullptr), rightChild(nullptr), height(0), color(BLACK), npl(0) {}; + BinNode(T const &val, BinNodePosi(T) p = nullptr, Color color = BLACK) : parent(p), leftChild(nullptr), rightChild(nullptr), data(val), height(0), color(color), npl(0) {}; int size() const; //compute the size of the tree rooted at current node BinNodePosi(T) insertAsLC(T const &val); //always assume that this.leftChild == nullptr diff --git a/thu_dsa/chp5/binTree.h b/thu_dsa/chp5/binTree.h index d6ea020..0eae418 100644 --- a/thu_dsa/chp5/binTree.h +++ b/thu_dsa/chp5/binTree.h @@ -12,8 +12,8 @@ class BinTree{ protected: BinNodePosi(T) __root; int __size; - bool updateHeight(BinNodePosi(T) x); - void updateHeightAbove(BinNodePosi(T) x); + virtual bool updateHeight(BinNodePosi(T) x); + virtual void updateHeightAbove(BinNodePosi(T) x); BinNodePosi(T) higherChild(BinNodePosi(T) x); public: diff --git a/thu_dsa/chp7/BST.h b/thu_dsa/chp7/BST.h index 95d740f..7bbcd3f 100644 --- a/thu_dsa/chp7/BST.h +++ b/thu_dsa/chp7/BST.h @@ -13,6 +13,7 @@ public: V value; //constructor + entry() = default; entry(K k, V v) : key(k), value(v) {} //overload operator diff --git a/thu_dsa/chp8/RedBlack.h b/thu_dsa/chp8/RedBlack.h new file mode 100644 index 0000000..3aa0397 --- /dev/null +++ b/thu_dsa/chp8/RedBlack.h @@ -0,0 +1,179 @@ +#ifndef REDBLACK_H_ +#define REDBLACK_H_ + +#include "../chp7/BST.h" + +#define ISBLACK(x) (!x || x->color == BLACK) +#define ISRED(x) (x && x->color == RED) +#define BLACK_HEIGHT(x) (x? x->height: 0) +#define BLACK_HEIGHT_CHANGED(x) (x && BLACK_HEIGHT(x->leftChild) != BLACK_HEIGHT(x->rightChild)) + +#define T entry +template +class RedBlack: public BST{ +protected: + BinNodePosi(T) zig(BinNodePosi(T) p); //right rotation + BinNodePosi(T) zag(BinNodePosi(T) p); //left rotation + void solveDoubleRed(BinNodePosi(T) x); + void solveDoubleBlack(BinNodePosi(T) x); + bool updateHeight(BinNodePosi(T) x); + +public: + BinNodePosi(T) insert(K const &key, V const &value); + bool remove(K const &key); +}; + +// protected methods + +template +BinNodePosi(T) RedBlack::zig(BinNodePosi(T) p){ + BinNodePosi(T) x = p->leftChild; + p->leftChild = x->rightChild; + if (x->rightChild) x->rightChild->parent = p; + + x->rightChild = p; + p->parent = x; + + updateHeight(p); + updateHeight(x); + return x; +} + +template +BinNodePosi(T) RedBlack::zag(BinNodePosi(T) p) { + BinNodePosi(T) x = p->rightChild; + p->rightChild = x->leftChild; + if (x->leftChild) x->leftChild->parent = p; + + x->leftChild = p; + p->parent = x; + + updateHeight(p); + updateHeight(x); + return x; +} + +template +bool RedBlack::updateHeight(BinNodePosi(T) x){ + if (!x) return false; + //else + int prevHeight = BLACK_HEIGHT(x); + if (ISBLACK(x->leftChild)) + x->height = BLACK_HEIGHT(x->leftChild) + 1; + else x->height = BLACK_HEIGHT(x->leftChild); + + return prevHeight != x->height; +} + +template +void RedBlack::solveDoubleRed(BinNodePosi(T) x){ + BinNodePosi(T) p = x->parent; + if (!p) { x->color = BLACK; return; } //x is __root + if (ISBLACK(p)) return; + //Double Red Exception + BinNodePosi(T) g = p->parent; //assert: g exists, for p is red + BinNodePosi(T) s = (p == g->leftChild ? g->rightChild : g->leftChild); //s is the uncle of x + + //case 1: s is black + if (ISBLACK(s)) { + BinNodePosi(T) gg = g->parent; + BinNodePosi(T) newRoot = rotateAt(x); + if (gg) + (g == gg->leftChild ? gg->leftChild : gg->rightChild) = newRoot; + newRoot->color = BLACK; + newRoot->leftChild->color = RED; + newRoot->rightChild->color = RED; + updateHeight(newRoot->leftChild); + updateHeight(newRoot->rightChild); + updateHeight(newRoot); + return; + } + //case2: s is red + else { + g->color = RED; + s->color = BLACK; + p->color = BLACK; + updateHeight(g); + solveDoubleRed(g); + return; + } +} + +template +void RedBlack::solveDoubleBlack(BinNodePosi(T) x){ + BinNodePosi(T) p = (x ? x->parent : __hot); + BinNodePosi(T) s = (x == p->leftChild ? p->rightChild : p->leftChild); + + //case one: s has at least one red child + if(ISRED(s->leftChild) || ISRED(s->rightChild)){ + BinNodePosi(T) redChild = ISRED(s->leftChild) ? s->leftChild : s->rightChild; + BinNodePosi(T) g = p->parent; + BinNodePosi(T) newRoot = rotateAt(redChild); + if(g) + (p == g->leftChild? g->leftChild: g->rightChild) = newRoot: + redChild->color = BLACK; + updateHeight(newRoot->leftChild); + updateHeight(newRoot->rightChild); + updateHeight(newRoot); + return; + } + //case two: p is red + if(ISRED(p)){ + p->color = BLACK; + s->color = RED; + updateHeight(p); + return; + } + //case three: p is black + if(ISBLACK(p)){ + p->color = BLACK; + s->color = RED; + updateHeight(p); + solveDoubleBlack(p); + return; + } + //case four: s is red + if(ISRED(s)){ + p->color = RED; + s->color = BLACK; + BinNodePosi(T) g = p->parent; + if(s == p->leftChild) zig(p); + else zag(p); + if (g) (p == g->leftChild ? g->leftChild : g->rightChild) = s; + solveDoubleBlack(x); + } + +} + +// public interfaces +template +BinNodePosi(T) RedBlack::insert(K const &key, V const &value){ + BinNodePosi(T) &x = search(key); + if (x) return x; + //else + x = new BinNode(entry(key, value), __hot, RED); + x->height = 1; //external black height + ++__size; + solveDoubleRed(x); + return x; +} + +template +bool RedBlack::remove(K const &key){ + BinNodePosi(T) &x = search(key); + if (!x) return false; + //else + BinNodePosi(T) succ = removeAt(x, __hot); + --__size; + if (ISRED(succ)) { + succ->color == BLACK; + return true; + } + if (!BLACK_HEIGHT_CHANGED(__hot)) return true; + solveDoubleBlack(succ); + return true; +} + +#undef T + +#endif diff --git a/thu_dsa/chp8/test_RedBlack.cpp b/thu_dsa/chp8/test_RedBlack.cpp new file mode 100644 index 0000000..e69de29