#ifndef BST_H_ #define BST_H_ #include "../chp5/binTree.h" #include using std::runtime_error; template class entry { public: K key; V value; //constructor entry() = default; entry(K k, V v) : key(k), value(v) {} //overload operator bool operator==(entry const e) { return key == e.key; } bool operator!=(entry const e) { return key != e.key; } bool operator>(entry const e) { return key > e.key; } bool operator<(entry const e) { return key < e.key; } }; #define T entry template class BST: public BinTree{ protected: BinNodePosi(T) __hot; BinNodePosi(T)& searchIn(BinNodePosi(T)& x, K const &key, BinNodePosi(T) &hot); BinNodePosi(T) connect34(BinNodePosi(T) x, BinNodePosi(T) y, BinNodePosi(T) z, BinNodePosi(T) T0, BinNodePosi(T) T1, BinNodePosi(T) T2, BinNodePosi(T) T3); //return new root BinNodePosi(T) rotateAt(BinNodePosi(T) x); //return new root BinNodePosi(T) removeAt(BinNodePosi(T) &x, BinNodePosi(T) &hot); public: //call by key, always assume that key exists, read-only V operator[](K const &key); virtual BinNodePosi(T)& search(K const &key); virtual BinNodePosi(T) insert(K const &key, V const &value); virtual bool remove(K const &key); }; //protected methods template BinNodePosi(T)& BST::searchIn(BinNodePosi(T)& x, K const &key, BinNodePosi(T) &hot){ if (!x || x->data.key == key) return x; hot = x; return key < x->data.key ? searchIn(x->leftChild, key, hot) : searchIn(x->rightChild, key, hot); } template BinNodePosi(T) BST::connect34(BinNodePosi(T) x, BinNodePosi(T) y, BinNodePosi(T) z, BinNodePosi(T) T0, BinNodePosi(T) T1, BinNodePosi(T) T2, BinNodePosi(T) T3){ x->leftChild = T0; x->rightChild = T1; if (T0) T0->parent = x; if (T1) T1->parent = x; updateHeight(x); z->leftChild = T2; z->rightChild = T3; if (T2) T2->parent = z; if (T3) T3->parent = z; updateHeight(z); x->parent = y; z->parent = y; y->leftChild = x; y->rightChild = z; updateHeight(y); return y; } template BinNodePosi(T) BST::rotateAt(BinNodePosi(T) x){ BinNodePosi(T) p = x->parent; BinNodePosi(T) g = p->parent; if(p == g->leftChild){ if (x == p->leftChild) { p->parent = g->parent; return connect34(x, p, g, x->leftChild, x->rightChild, p->rightChild, g->rightChild); } else { x->parent = g->parent; return connect34(p, x, g, p->leftChild, x->leftChild, x->rightChild, g->rightChild); } }else{ if (x == p->leftChild) { x->parent = g->parent; return connect34(g, x, p, g->leftChild, x->leftChild, x->rightChild, p->rightChild); } else { p->parent = g->parent; return connect34(g, p, x, g->leftChild, p->leftChild, x->leftChild, x->rightChild); } } } template BinNodePosi(T) BST::removeAt(BinNodePosi(T) &x, BinNodePosi(T) &hot){ BinNodePosi(T) succ; if (!x->leftChild) succ = x = x->rightChild; else if (!x->rightChild) succ = x = x->leftChild; else{ succ = x->succ(); x->data = succ->data; if (succ->parent == x) succ->parent->rightChild = succ->rightChild; else succ->parent->leftChild = succ->rightChild; hot = succ->parent; succ = succ->rightChild; } if(succ) succ->parent = hot; return succ; } //public interfaces template V BST::operator[](K const &key){ BinNodePosi(T) x = search(key); if (!x) throw runtime_error("Fatal Error: key doesn't exist."); return x->data.value; } template BinNodePosi(T)& BST::search(K const &key){ return searchIn(__root, key, __hot = nullptr); } template BinNodePosi(T) BST::insert(K const &key, V const &value){ BinNodePosi(T) &x = search(key); if (x) return x; x = new BinNode(entry(key, value), __hot); ++__size; updateHeightAbove(__hot); return x; } template bool BST::remove(K const &key){ BinNodePosi(T) &x = search(key); if (!x) return false; removeAt(x, __hot); --__size; updateHeightAbove(__hot); return true; } #undef T #endif