Pagini recente » Cod sursa (job #2149591) | Cod sursa (job #974927) | Cod sursa (job #417932) | Cod sursa (job #1961053) | Cod sursa (job #2451567)
#include <iostream>
#include <fstream>
#include <cassert>
std::ifstream fin("algsort.in");
std::ofstream fout("algsort.out");
template<class T>
class RedBlackTree{
private:
enum class Color{
Red, Black
};
struct Node{
Node* parent;
Node* left;
Node* right;
Color color;
T key;
};
// Helper functions
Node* getParent(Node* n)
{
// The parent is going to be null if n is root node
return n->parent;
}
Node* getGrandParent(Node* n)
{
Node* p = getParent(n);
if (p == nullptr) // no parent, no grandparent
return nullptr;
// The grandparent is going to be null if n is root node
return getParent(p);
}
Node* getSibling(Node* n)
{
Node* p = getParent(n);
if (p == nullptr) // no parent, no sibling
return nullptr;
if (n == p->left)
return p->right;
return p->left;
}
Node* getUncle(Node* n)
{
Node* p = getParent(n);
if (p == nullptr) // no parent, no uncle
return nullptr;
return getSibling(p);
}
void rotateLeft(Node* n)
{
Node* p = getParent(n);
Node* nnew = n->right;
assert(nnew != nullptr); // right son of n can't be null
n->right = nnew->left;
nnew->left = n;
n->parent = nnew;
if (n->right != nullptr)
n->right->parent = n;
if (p != nullptr)
{
if (n == p->left)
p->left = nnew;
else
p->right = nnew;
}
nnew->parent = p;
}
void rotateRight(Node* n)
{
Node* p = getParent(n);
Node* nnew = n->left;
assert(nnew != nullptr); // left son of n can't be null
n->left = nnew->right;
nnew->right = n;
n->parent = nnew;
if (n->left != nullptr)
n->left->parent = n;
if (p != nullptr)
{
if (n == p->left)
p->left = nnew;
else
p->right = nnew;
}
nnew->parent = p;
}
public:
class iterator{
public:
iterator()
: ptr{nullptr}
{}
iterator(const iterator& other)
: ptr{new Node(other.ptr)}
{}
iterator(iterator&& other)
: ptr{std::move(other.ptr)}
{
other.ptr = nullptr;
}
iterator(const Node& ptr)
: ptr{new Node(ptr)}
{}
iterator& operator++()
{
if (ptr->right != nullptr)
{
ptr = ptr->right;
while (ptr->left != nullptr)
ptr = ptr->left;
return *this;
}
while (ptr->parent != nullptr &&
ptr->parent->right == ptr)
ptr = ptr->parent;
ptr = ptr->parent;
return *this;
}
T& operator *()
{
return ptr->key;
}
bool operator !=(const iterator& other) const
{
return ptr != other.ptr;
}
~iterator()
{
delete ptr;
}
private:
Node* ptr;
};
RedBlackTree() : root{nullptr}
{}
void insert(const T& key)
{
Node* nnew = new Node;
nnew->key = key;
root = Insert(root, nnew);
}
void insert(T&& key)
{
Node* nnew = new Node;
nnew->key = key;
root = Insert(root, nnew);
}
iterator begin()
{
Node* node = new Node(*root);
while (node->left != nullptr)
node = node->left;
return *node;
}
iterator end()
{
return iterator();
}
void WriteAll()
{
WriteAll(root);
}
private:
Node* root;
void WriteAll(Node* n)
{
if (n == nullptr)
return;
WriteAll(n->left);
std::cout << n->key << ' ';
WriteAll(n->right);
}
Node* Insert(Node* root, Node* n)
{
// Insert the Node into the tree, just like you'd do
// with a bynary search tree
InsertRecurse(root, n);
// And the repair the tree in case some rules
// have been violated
InsertRepairTree(n);
root = n;
while (getParent(root) != nullptr)
root = getParent(root);
return root;
}
void InsertRecurse(Node* root, Node* n)
{
if (root != nullptr && n->key < root->key)
{
if (root->left != nullptr)
{
InsertRecurse(root->left, n);
return;
}
else
root->left = n;
}
else if (root != nullptr)
{
if (root->right != nullptr)
{
InsertRecurse(root->right, n);
return;
}
else
root->right = n;
}
// Insert new Node n:
n->parent = root;
n->left = nullptr;
n->right = nullptr;
n->color = Color::Red;
}
void InsertRepairTree(Node* n)
{
if (getParent(n) == nullptr)
InsertCase1(n);
else if (getParent(n)->color == Color::Black)
InsertCase2(n);
else if (getUncle(n) != nullptr
&& getUncle(n)->color == Color::Red)
InsertCase3(n);
else
InsertCase4(n);
}
void InsertCase1(Node* n) // n is the root of the tree
{ // => we change its color to BLACK
n->color = Color::Black;
}
void InsertCase2(Node* n) // Cuurent node's parent is BLACK
{ // => EVERY RULE is respected
}
void InsertCase3(Node* n) // Both the parent and uncle are RED
{
// => Repaint parent, uncle and grandparent
getParent(n)->color = Color::Black;
getUncle(n)->color = Color::Black;
getGrandParent(n)->color = Color::Red;
// Now the grandparent could be violating rules
// so we need to fix this by calling InsertRepairTree()
// for the grandparent
InsertRepairTree(getGrandParent(n));
}
void InsertCase4(Node* n) // Parent is RED, Uncle is BLACK
{
Node* p = getParent(n);
Node* g = getGrandParent(n);
// First I make sure that n is "outside" of the subtree
// under G (left of left of g or right of right of g)
if (n == p->right && p == g->left)
{
rotateLeft(p);
n = n->left;
}
else if (n == p->left && p == g->right)
{
rotateRight(p);
n = n->right;
}
// And then I rotate in such a way that the parent
// will be where the grandparent((will be turned to)BLACK)
// was and will have as children the grandparent and
// node n, (both (will be turned to) RED)
p = getParent(n);
g = getGrandParent(n);
if (n == p->left)
rotateRight(g);
else
rotateLeft(g);
p->color = Color::Black;
g->color = Color::Red;
}
};
int main()
{
RedBlackTree<int> rbt;
int n, x;
fin >> n;
for (int i = 1; i <= n; ++i)
{
fin >> x;
rbt.insert(x);
}
for (const int& v : rbt)
fout << v << ' ';
fin.close();
fout.close();
return 0;
}