// 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;
}