create Red-Black tree head file, not tested yet.
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
|
||||
#define BinNodePosi(T) BinNode<T>*
|
||||
|
||||
typedef enum{RED, BLACK} Color;
|
||||
|
||||
template <typename T>
|
||||
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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
V value;
|
||||
|
||||
//constructor
|
||||
entry() = default;
|
||||
entry(K k, V v) : key(k), value(v) {}
|
||||
|
||||
//overload operator
|
||||
|
||||
179
thu_dsa/chp8/RedBlack.h
Normal file
179
thu_dsa/chp8/RedBlack.h
Normal file
@@ -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<K, V>
|
||||
template <typename K, typename V>
|
||||
class RedBlack: public BST<K, V>{
|
||||
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 <typename K, typename V>
|
||||
BinNodePosi(T) RedBlack<K, V>::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 <typename K, typename V>
|
||||
BinNodePosi(T) RedBlack<K, V>::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 <typename K, typename V>
|
||||
bool RedBlack<K, V>::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 <typename K, typename V>
|
||||
void RedBlack<K, V>::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 <typename K, typename V>
|
||||
void RedBlack<K, V>::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 <typename K, typename V>
|
||||
BinNodePosi(T) RedBlack<K, V>::insert(K const &key, V const &value){
|
||||
BinNodePosi(T) &x = search(key);
|
||||
if (x) return x;
|
||||
//else
|
||||
x = new BinNode<T>(entry<K, V>(key, value), __hot, RED);
|
||||
x->height = 1; //external black height
|
||||
++__size;
|
||||
solveDoubleRed(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
bool RedBlack<K, V>::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
|
||||
0
thu_dsa/chp8/test_RedBlack.cpp
Normal file
0
thu_dsa/chp8/test_RedBlack.cpp
Normal file
Reference in New Issue
Block a user