Department of Computer Science | Institute of Theoretical Computer Science | CADMO

Theory of Combinatorial Algorithms

Prof. Emo Welzl and Prof. Bernd Gärtner

// Implementation of Treap class (Randomized Binary Search Tree) #include "Treap.h" #include #include #include #include Treap::Treap() : root_(0) {} Treap::Treap(const Treap& other) : root_(0) { root_ = copy (other.root_); } TreapNode* Treap::copy (const TreapNode* current) { if (current != 0) { return new TreapNode (current->get_key(), current->get_priority(), copy(current->get_left()), copy(current->get_right())); } else return 0; } Treap& Treap::operator= (const Treap& other) { if (root_ != other.root_) { //check for self-assignment clear(); root_ = copy (other.root_); } return *this; } Treap::~Treap() { clear(); } void Treap::clear() { clear_subtree(root_); root_ = 0; } void Treap::clear_subtree(TreapNode* current) { if (current != 0) { clear_subtree(current->left_); clear_subtree(current->right_); delete current; } } void Treap::insert(const int key) { insert (root_, key, std::rand()); } void Treap::insert (TreapNode*& current, const int key, const int priority) { if (current == 0) current = new TreapNode (key, priority); else if (key < current->key_) { insert (current->left_, key, priority); if (priority > current->get_priority()) rotate_right (current); } else { insert (current->right_, key, priority); if (priority > current->get_priority()) rotate_left (current); } } void Treap::rotate_left (TreapNode*& current) { assert (current->right_ != 0); TreapNode* old_current = current; current = current->right_; old_current->right_ = current->left_; current->left_ = old_current; } void Treap::rotate_right (TreapNode*& current) { assert (current->left_ != 0); TreapNode* old_current = current; current = current->left_; old_current->left_ = current->right_; current->right_ = old_current; } void Treap::remove(const int key) { remove (root_, key); } void Treap::remove(TreapNode*& current, const int key) { if (current == 0) return; if (key < current->key_) return remove (current->left_, key); if (key > current->key_) return remove (current->right_, key); assert (key == current->key_); remove_root (current); } void Treap::remove_root (TreapNode*& current) { assert (current != 0); if (current->left_ != 0 && (current->right_ == 0 || current->left_->priority_ > current->right_->priority_)) { rotate_right (current); return remove_root (current->right_); } if (current->right_ != 0 && (current->left_ == 0 || current->right_->priority_ >= current->left_->priority_)) { rotate_left (current); return remove_root (current->left_); } // now we have a leaf assert (current->left_ == 0 && current->right_ == 0); delete current; current = 0; } const TreapNode* Treap::find(const int key) const { const TreapNode* current = root_; while (current != 0 && current->get_key() != key) if (key < current->get_key()) current = current->get_left(); else current = current->get_right(); return current; } // This method is not very efficient but the issue is only the function size() that is O(n) where n is the number of the nodes in the list. One can do this in O(1) by storing the size of the tree rooted on the node as a field of the node. // PRE: *this is not an empty tree // returns the median of the sequnce stored in *this int Treap::median() const { assert(root_ != 0); const int medianPos = size() / 2; const TreapNode* current = root_; // smaller than current int smaller = size(current->get_left()); while (smaller != medianPos) { if (smaller < medianPos) { current = current->get_right(); assert(current != 0); smaller += size(current->get_left()) + 1; } else { current = current->get_left(); assert(current != 0); smaller = smaller - size(current->get_right()) - 1; } } return current->get_key(); } int Treap::remove_max() { assert (root_ != 0); return remove_max (root_); } int Treap::remove_min() { assert (root_ != 0); return remove_min (root_); } int Treap::remove_max(TreapNode*& current) { assert (current != 0); if (current->get_right() != 0) return remove_max (current->right_); else { int result = current->get_key(); remove_root (current); return result; } } int Treap::remove_min(TreapNode*& current) { assert (current != 0); if (current->get_left() != 0) return remove_min (current->left_); else { int result = current->get_key(); remove_root (current); return result; } } int Treap::height() const { return height(root_); } int Treap::height(const TreapNode* current) const { if (current == 0) return -1; else return 1 + std::max(height(current->get_left()), height(current->get_right())); } int Treap::size() const { return size(root_); } int Treap::size(const TreapNode* current) const { if (current == 0) return 0; return 1 + size(current->get_left()) + size(current->get_right()); } const TreapNode* Treap::get_root() const { return root_; } void Treap::print_preorder(std::ostream& o) const { print_preorder(o, root_); } void Treap::print_preorder(std::ostream& o, const TreapNode* current) const { if (current != 0) { o << current->get_key() << " "; print_preorder(o, current->get_left()); print_preorder(o, current->get_right()); } } void Treap::print_postorder(std::ostream& o) const { print_postorder(o, root_); } void Treap::print_postorder(std::ostream& o, const TreapNode* current) const { if (current != 0) { print_postorder(o, current->get_left()); print_postorder(o, current->get_right()); o << current->get_key() << " "; } } void Treap::print(std::ostream& o) const { print(o, root_); } void Treap::print(std::ostream& o, const TreapNode* current) const { if (current != 0) { print(o, current->get_left()); o << current->get_key() << " "; print(o, current->get_right()); } } void Treap::pretty_print (std::ostream& o) const { for (double row = 0; row < size(); row+=0.5) { print_row (o, row); o << std::endl; } } void Treap::print_row (std::ostream& o, double row) const { char last = 'x'; const TreapNode* current = root_; while (current != 0) { if (row < size(current->get_right())) { // 'r' if (last == 'l') o << "| "; else o << " "; last = 'r'; current = current->get_right(); continue; } if (row > size(current->get_right())) { // 'l' if (last == 'r') o << "| "; else o << " "; last = 'l'; row = row - size(current->get_right()) - 1; current = current->get_left(); continue; } assert (row == size(current->get_right())); o << " --(" << current->get_key() << ")"; break; } } bool Treap::is_valid () const { int min, max; return (root_ == 0 || is_binary_search_tree (root_, min, max) && is_heap(root_)); } bool Treap::is_binary_search_tree (const TreapNode* current, int& min, int& max) const { assert (current != 0); min = max = current->get_key(); int min_r = max; int max_l = min; bool ok_l = true; bool ok_r = true; if (current->get_left() != 0) ok_l = is_binary_search_tree (current->get_left(), min, max_l); if (current->get_right() != 0) ok_r = is_binary_search_tree (current->get_right(), min_r, max); return (ok_l && ok_r && max_l <= current->get_key() && current->get_key() <= min_r); } bool Treap::is_heap (const TreapNode* current) const { assert (current != 0); if (current->get_left() != 0) if (!is_heap (current->get_left()) || current->get_priority() < current->get_left()->get_priority()) return false; if (current->get_right() != 0) if (!is_heap (current->get_right()) || current->get_priority() < current->get_right()->get_priority()) return false; return true; } std::ostream& operator<< (std::ostream& o, const Treap& tree) { tree.print(o); return o; }