Cod sursa(job #1320335)

Utilizator tweetyMarinescu Ion tweety Data 17 ianuarie 2015 20:50:09
Problema Sortare prin comparare Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 17.94 kb
#include <fstream>
#include <iostream>
using namespace std;

ifstream in("algsort.in");
ofstream out("algsort.out");

template <typename T>
class BinaryTreeNode
{
public:
    /** CONSTRUCTOR/DESTRUCTOR METHODS **/

    //ctor - initialization with T data and null children
    BinaryTreeNode(const T& data) : m_data(data), m_parent(NULL), m_left(NULL), m_right(NULL)
    {

    }

    //dtor - unlinks the node from its left/right children and its parent
    virtual ~BinaryTreeNode()
    {
        unlinkAll();
    }

    /** LINK/UNLINK METHODS **/

    //make both children = null
    void unlinkAll()
    {
        unlinkParent();
        unlinkLeft();
        unlinkRight();
    }

    //make the parent of the node = null
    void unlinkParent()
    {
        setParent(NULL);
    }

    //make left child = null
    void unlinkLeft()
    {
        setLeft(NULL);
    }

    //make right child = null
    void unlinkRight()
    {
        setRight(NULL);
    }

    /** SET METHODS **/

    //change node's parent
    void setParent(BinaryTreeNode<T>* parent)
    {
        m_parent = parent;
    }

    //change left child
    void setLeft(BinaryTreeNode<T>* left)
    {
        m_left = left;

        if (left)
            left->setParent(this);
    }

    //change right child
    void setRight(BinaryTreeNode<T>* right)
    {
        m_right = right;

        if (right)
            right->setParent(this);
    }

    //change the T data of the node
    void setData(const T& data)
    {
        m_data = data;
    }

    /** GET METHODS **/

    //returns pointer to parent node
    virtual BinaryTreeNode<T>* getParent() const
    {
        return m_parent;
    }

    //returns pointer to left child
    virtual BinaryTreeNode<T>* getLeft() const
    {
        return m_left;
    }

    //returns pointer to right child
    virtual BinaryTreeNode<T>* getRight() const
    {
        return m_right;
    }

    //returns data of current node
    T getData() const
    {
        return m_data;
    }

    //returns number of children
    int getChildren() const
    {
        int children = 0;

        if (getLeft())
            children++;

        if (getRight())
            children++;

        return children;
    }

    /** BOOL METHODS **/

    //checks whether this node is the left child of `node`
    bool isLeftChildOf(BinaryTreeNode<T>* node)
    {
        if (!node || node->getLeft() != this)
            return false;

        return true;
    }

    //checks whether this node is the right child of `node`
    bool isRightChildOf(BinaryTreeNode<T>* node)
    {
        if (!node || node->getRight() != this)
            return false;

        return true;
    }

protected:
    //the data which current node contains (information)
    T m_data;
    //pointer to node's parent
    BinaryTreeNode<T>* m_parent;
    //pointer to left child
    BinaryTreeNode<T>* m_left;
    //pointer to right child
    BinaryTreeNode<T>* m_right;
};

template<typename T>
class AvlTreeNode : public BinaryTreeNode<T>
{
public:
    /** CONSTRUCTOR/DESTRUCTOR METHODS **/

    //ctor - calls parent's ctor and does initialization
    AvlTreeNode(const T& data) : BinaryTreeNode<T>(data), m_balanceFactor('=')
    {

    }

    //dtor - prevents compiler from generating default dtor
    ~AvlTreeNode()
    {

    }

    /** GET METHODS **/

    //returns pointer to parent node
    AvlTreeNode<T>* getParent() const override
    {
        return static_cast<AvlTreeNode<T>*>(this->m_parent);
    }

    //returns pointer to left child
    AvlTreeNode<T>* getLeft() const override
    {
        return static_cast<AvlTreeNode<T>*>(this->m_left);
    }

    //returns pointer to right child
    AvlTreeNode<T>* getRight() const override
    {
        return static_cast<AvlTreeNode<T>*>(this->m_right);
    }

    //returns the balance of this node
    char getBalance() const
    {
        return m_balanceFactor;
    }

    /** SET METHODS **/

    //subtree rooted in this node has deepened in left
    void setLeftBalance()
    {
        m_balanceFactor = 'L';
    }

    //balance was established
    void setEqualBalance()
    {
        m_balanceFactor = '=';
    }

    //subtree deepens in right
    void setRightBalance()
    {
        m_balanceFactor = 'R';
    }

private:
    //balance for the subtree rooted in this node
    char m_balanceFactor;
};

template<typename T>
class BinarySearchTree
{
public:
    /** CONSTRUCTOR/DESTRUCTOR METHODS **/

    //ctor - initializes tree's root to null
    BinarySearchTree() : m_root(NULL)
    {

    }

    //dtor - does memory management by removing all the nodes
    virtual ~BinarySearchTree()
    {
        removeAll(getRoot());
        m_root = NULL;
    }

    /** TREE TRAVERSALS METHODS **/

    //prints values in sorted order
    void inorderPrint(BinaryTreeNode<T>* root)
    {
        if (root)
        {
            inorderPrint(root->getLeft());
            out << root->getData() << " ";
            inorderPrint(root->getRight());
        }
    }

    /** SUCC/PRED METHODS **/

    //returns next element from `data` in sorted order. runs in O(h) due to call to search
    T successor(const T& data)
    {
        BinaryTreeNode<T>* node = successorNode(search(data));
        if (node)
            return node->getData();

        return false;
    }

    //returns prev element from `data` in sorted order. runs in O(h) due to call to search
    T predecessor(const T& data)
    {
        BinaryTreeNode<T>* node = predecessorNode(search(data));
        if (node)
            return node->getData();

        return false;
    }

    /** MIN/MAX METHODS **/

    //returns maximum of the BST
    T max()
    {
        return (maxNode(getRoot()))->getData();
    }

    //returns minimum of the BST
    T min()
    {
        return (minNode(getRoot()))->getData();
    }

    /** GET METHODS **/

    //returns pointer to root of the BST
    virtual BinaryTreeNode<T>* getRoot() const
    {
        return m_root;
    }

    /** BOOL METHODS **/

    //checks whether the tree is empty
    bool isEmpty() const
    {
        return getRoot() == NULL;
    }

    //checks whether a certain value exists in the BST. runs in O(h)
    bool isInserted(const T& data) const
    {
        return search(data) != NULL;
    }

    /** ADD/REMOVE METHODS **/

    //inserts a new element in the BST. runs in O(h)
    virtual void insert(const T& data)
    {
        BinaryTreeNode<T>* root = getRoot();
        BinaryTreeNode<T>* node = new BinaryTreeNode<T>(data);

        if (!root)
        {
            setRoot(node);
            return;
        }

        while (root != NULL)
        {
            if (node->getData() < root->getData())
                if (root->getLeft())
                    root = root->getLeft();
                else
                {
                    root->setLeft(node);
                    break;
                }
            else
                if (root->getRight())
                    root = root->getRight();
            else
            {
                root->setRight(node);
                break;
            }
        }
    }

    //remove the node which contains `data`, if it exists. runs in O(h) due to call to search
    void remove(const T& data)
    {
        removeNode(search(data));
    }

    //bad
    void remove(BinaryTreeNode<T>* node)
    {
        removeNode(node);
    }

    //removes every node from the subtree rooted at root
    void removeAll(BinaryTreeNode<T>* root)
    {
        if (root)
        {
            removeAll(root->getLeft());
            removeAll(root->getRight());
            delete root;
        }
    }

public:
    //pointer to the root node of the BST
    BinaryTreeNode<T>* m_root;

    /** SEARCH/ADD/REMOVE AND OTHER PRIVATE METHODS **/

    //returns pointer to node which contains certain data or null if it's not found. runs in O(h)
    BinaryTreeNode<T>* search(const T& data) const
    {
        BinaryTreeNode<T>* temp = getRoot();

        while (temp && temp->getData() != data)
            if (data > temp->getData())
                temp = temp->getRight();
            else
                temp = temp->getLeft();

        return temp;
    }

    //changes the root node
    void setRoot(BinaryTreeNode<T>* root)
    {
        m_root = root;

        if (root)
            root->unlinkParent();
    }

    //swaps node and next, changing the root accordingly
    void swapNodes(BinaryTreeNode<T>* node, BinaryTreeNode<T>* next)
    {
        BinaryTreeNode<T>* parent = node->getParent();
        if (parent)
            if (node->isLeftChildOf(parent))
                parent->setLeft(next);
            else
                parent->setRight(next);
        else
            setRoot(next);
    }

    //removes a certain node from the BST
    void removeNode(BinaryTreeNode<T>* node)
    {
        if (!node)
            return;

        BinaryTreeNode<T>* next;
        switch (node->getChildren())
        {
        case 0:
            {
                next = NULL;
                break;
            }

        case 1:
            {
                if (node->getLeft())
                    next = node->getLeft();
                else
                    next = node->getRight();

                break;
            }

        case 2:
            {
                next = successorNode(node);

                if (next->isRightChildOf(node))
                    next->setLeft(node->getLeft());
                else
                {
                    next->getParent()->setLeft(next->getRight());
                    next->setLeft(node->getLeft());
                    next->setRight(node->getRight());
                }

                break;
            }
        }

        swapNodes(node, next);
        delete node;
    }

    /** MIN/MAX (OF) METHODS **/

    //returns pointer to node with minimum value in the root subtree or null if the node given already contains the minimum
    BinaryTreeNode<T>* minNode(BinaryTreeNode<T>* root)
    {
        while (root->getLeft())
            root = root->getLeft();

        return root;
    }

    //returns pointer to node with maximum value in the 'root' subtree or null if the node given already contains the maximum
    BinaryTreeNode<T>* maxNode(BinaryTreeNode<T>* root)
    {
        while (root->getRight())
            root = root->getRight();

        return root;
    }

    /** SUCCESSOR/PREDECESSOR METHODS **/

    //returns pointer to the `next` (by data value) node or null if such node does not exist
    BinaryTreeNode<T>* successorNode(BinaryTreeNode<T>* root)
    {
        if (root->getRight())
            return minNode(root->getRight());

        BinaryTreeNode<T>* parent = root->getParent();
        while (parent && root == parent->getRight())
        {
            root = parent;
            parent = parent->getParent();
        }

        return parent;
    }

    //returns pointer to the `prev` (by data value) node or null if such node does not exist
    BinaryTreeNode<T>* predecessorNode(BinaryTreeNode<T>* root)
    {
        if (root->getLeft())
            return maxNode(root->getLeft());

        BinaryTreeNode<T>* parent = root->getParent();
        while (parent && root == parent->getLeft())
        {
            root = parent;
            parent = parent->getParent();
        }

        return parent;
    }
};

template<typename T>
class AvlTree : public BinarySearchTree<T>
{
public:
    /** CONSTRUCTOR/DESTRUCTOR METHODS **/

    //ctor - calls parent ctor to do initialization
    AvlTree() : BinarySearchTree<T>()
    {

    }

    //dtor - prevents compiler from generating default dtor
    ~AvlTree()
    {

    }

    /** GET METHODS **/

    //returns pointer to root of the BST
    AvlTreeNode<T>* getRoot() const override
    {
        return static_cast<AvlTreeNode<T>*>(this->m_root);
    }

    /** ADD/REMOVE METHODS **/

    //inserts a new element in the AVL
    void insert(const T& data) override
    {
        AvlTreeNode<T>* root = getRoot();
        AvlTreeNode<T>* fuckedUp = NULL;
        AvlTreeNode<T>* node = new AvlTreeNode<T>(data);

        if (!root)
        {
            this->setRoot(node);
            return;
        }

        while (root != NULL)
        {
            if (root->getBalance() != '=')
                fuckedUp = root;

            if (node->getData() < root->getData())
                if (root->getLeft())
                    root = root->getLeft();
                else
                {
                    root->setLeft(node);
                    break;
                }
            else
                if (root->getRight())
                    root = root->getRight();
                else
                {
                    root->setRight(node);
                    break;
                }
        }

        rebalanceTree(fuckedUp, node);
    }

    //prints values in sorted order
    void inorderPrint(AvlTreeNode<T>* root)
    {
        if (root)
        {
            inorderPrint(root->getLeft());
            out << root->getData() << " ";
            inorderPrint(root->getRight());
        }
    }


private:

    void rebalanceTree(AvlTreeNode<T>* fuckedUp, AvlTreeNode<T>* node)
    {
        AvlTreeNode<T>* root = getRoot();

        //tree was perfectly balanced
        if (fuckedUp == NULL)
        {
            if (node->getData() < root->getData())
                root->setLeftBalance();
            else
                root->setRightBalance();

            updateBalanceBetween(root, node);
            return;
        }

        //was left and new goes right or vice versa => set perfect balance
        if ((fuckedUp->getBalance() == 'L' && node->getData() > fuckedUp->getData()) || (fuckedUp->getBalance() == 'R' && node->getData() < fuckedUp->getData()))
        {
            fuckedUp->setEqualBalance();
            updateBalanceBetween(fuckedUp, node);
            return;
        }

        //1. right rotation
        if (fuckedUp->getBalance() == 'L' && node->getData() < fuckedUp->getLeft()->getData())
        {
            fuckedUp->setEqualBalance();
            rotateRight(fuckedUp);
            updateBalanceBetween(fuckedUp->getParent(), node);
            return;
        }

        //2. left rotation
        if (fuckedUp->getBalance() == 'R' && node->getData() > fuckedUp->getRight()->getData())
        {
            fuckedUp->setEqualBalance();
            rotateLeft(fuckedUp);
            updateBalanceBetween(fuckedUp->getParent(), node);
            return;
        }

        //3. left left rotation
        if (fuckedUp->getBalance() == 'L' && node->getData() > fuckedUp->getLeft()->getData())
        {
            rotateLeft(fuckedUp->getLeft());
            rotateRight(fuckedUp);
            updateBalanceLR(fuckedUp, node);
            return;
        }

        //4. right right rotation
        if (fuckedUp->getBalance() == 'R' && node->getData() < fuckedUp->getRight()->getData())
        {
            rotateRight(fuckedUp->getRight());
            rotateLeft(fuckedUp);
            updateBalanceRL(fuckedUp, node);
            return;
        }
    }

    void updateBalanceBetween(AvlTreeNode<T>* from, AvlTreeNode<T>* to)
    {
        for (AvlTreeNode<T>* temp = to->getParent(); temp != from && temp != NULL; temp = temp->getParent())
            if (from->getData() < temp->getData())
                temp->setLeftBalance();
            else
                temp->setRightBalance();
    }

    void updateBalanceLR(AvlTreeNode<T>* to, AvlTreeNode<T>* from)
    {
        if (to == getRoot())
        {
            to->setEqualBalance();
            return;
        }

        if (from->getData() < to->getParent()->getData())
        {
            to->setRightBalance();
            updateBalanceBetween(to->getParent()->getLeft(), from);
            return;
        }

        to->setEqualBalance();
        to->getParent()->getLeft()->setLeftBalance();
        updateBalanceBetween(to, from);
    }

    void updateBalanceRL(AvlTreeNode<T>* to, AvlTreeNode<T>* from)
    {
        if (to == getRoot())
        {
            to->setEqualBalance();
            return;
        }

        if (from->getData() > to->getParent()->getData())
        {
            to->setLeftBalance();
            updateBalanceBetween(to->getParent()->getRight(), from);
            return;
        }

        to->setEqualBalance();
        to->getParent()->getRight()->setRightBalance();
        updateBalanceBetween(to, from);
    }

    void rotateRight(AvlTreeNode<T>* node)
    {
        AvlTreeNode<T>* temp = node->getLeft();
        node->setLeft(temp->getRight());

        if (node == getRoot())
            this->setRoot(temp);
        else
            if (node->getParent()->getLeft() == node)
                node->getParent()->setLeft(temp);
            else
                node->getParent()->setRight(temp);

        temp->setRight(node);
    }

    void rotateLeft(AvlTreeNode<T>* node)
    {
        AvlTreeNode<T>* temp = node->getRight();
            node->setRight(temp->getLeft());

        if (node == getRoot())
            this->setRoot(temp);
        else
            if (node->getParent()->getRight() == node)
                node->getParent()->setRight(temp);
            else
                node->getParent()->setLeft(temp);

        temp->setLeft(node);
    }
};



int main()
{
    BinarySearchTree<int> bst;
    int N;

    in >> N;
    for (int i = 0; i != N; ++i)
    {
        int x;
        in >> x;
        bst.insert(x);
    }

    bst.inorderPrint(bst.getRoot());

    return 0;
}