Cod sursa(job #1419453)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 15 aprilie 2015 17:27:17
Problema Sortare prin comparare Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 6.51 kb
#include <bits/stdc++.h>

using namespace std;

class BinomialHeap
{
private:

    class Node
    {
    public:

        int key;
        int degree;

        Node *parent;
        Node *child;
        Node *sibling;

        Node() : key(0), degree(0), parent(nullptr), child(nullptr), sibling(nullptr) {
        }

        Node(const int k) : key(k), degree(0), parent(nullptr), child(nullptr), sibling(nullptr) {
        }
    };

    Node *head;

    BinomialHeap(Node* aux) : head(aux), dim(0) {
    }

    BinomialHeap& operator = (const BinomialHeap *BH)
    {
        *this = BH;
        return *this;
    }

    void combineTrees(Node *&y, Node *&z) /// O(1)
    {
        /// y and z have same degree
        /// y becomes son of z
        y->parent = z;
        y->sibling = z->child;
        z->child = y;
        z->degree++;
    }

    Node* mergeLists(BinomialHeap &heap1, BinomialHeap &heap2) /// ~O(logN)
    {
        if (heap1.head == nullptr)
            return heap2.head;

        if (heap2.head == nullptr)
            return heap1.head;

        Node *head = nullptr;
        Node *heap1Next = heap1.head;
        Node *heap2Next = heap2.head;

        if (heap1.head->degree <= heap2.head->degree)
        {
            head = heap1.head;
            heap1Next = heap1Next->sibling;
        }
        else
        {
            head = heap2.head;
            heap2Next = heap2Next->sibling;
        }

        Node *tail = head;

        while (heap1Next != nullptr && heap2Next != nullptr)
        {
            if (heap1Next->degree <= heap2Next->degree)
            {
                tail->sibling = heap1Next;
                heap1Next = heap1Next->sibling;
            }
            else
            {
                tail->sibling = heap2Next;
                heap2Next = heap2Next->sibling;
            }

            tail = tail->sibling;
        }

        while (heap1Next != nullptr)
        {
            tail->sibling = heap1Next;
            tail = tail->sibling;
            heap1Next = heap1Next->sibling;
        }

        while (heap2Next != nullptr)
        {
            tail->sibling = heap2Next;
            tail = tail->sibling;
            heap2Next = heap2Next->sibling;
        }

        return head;
    }

    Node* join(BinomialHeap &heap) /// O(logN)
    {
        Node *newHead = mergeLists(*this, heap);

        this->head = nullptr;
        heap.head = nullptr;

        if (newHead == nullptr)
            return nullptr;

        Node *prev = nullptr;
        Node *curr = newHead;
        Node *next = curr->sibling;

        while (next != nullptr)
        {
            if (curr->degree != next->degree || (next->sibling != nullptr && next->sibling->degree == curr->degree))
            {
                prev = curr;
                curr = next;
            }
            else if (curr->key < next->key)
            {
                curr->sibling = next->sibling;
                combineTrees(next, curr);
            }
            else
            {
                if (prev == nullptr)
                    newHead = next;
                else
                    prev->sibling = next;

                combineTrees(curr, next);
                curr = next;
            }

            next = curr->sibling;
        }

        return newHead;
    }

    void insert(const int key) /// O(logN)
    {
        Node *newNode = new Node(key);
        BinomialHeap tempHeap(newNode);
        this->head = this->join(tempHeap);
        dim++;
    }

    int findMinimum() const /// O(logN)
    {
        if (this->head == nullptr)
            return numeric_limits<int>::max();
        else
        {
            Node *minim = head;
            Node *next = minim->sibling;

            while (next != nullptr)
            {
                if (minim->key > next->key)
                    minim = next;

                next = next->sibling;
            }

            return minim->key;
        }
    }

    void decreaseKey(Node *&node, const int newKey) /// O(logN)
    {
        if (newKey > node->key)
            throw "Error in decreaseKey: newKey is not smaller!";

        node->key = newKey;
        Node *y = node;
        Node *z = y->parent;

        while (z != nullptr && y->key < z->key)
        {
            swap(y->key, z->key);
            y = z;
            z = y->parent;
        }
    }

    void removeTreeRoot(Node *&root, Node *&prevRoot) /// O(logN)
    {
        /// Remove root from the heap
        if (root == this->head)
            this->head = root->sibling;
        else
            prevRoot->sibling = root->sibling;

        /// Reverse the order of root's children
        Node *newHead = nullptr;
        Node *child = root->child;

        delete root;

        while (child != nullptr)
        {
            Node *next = child->sibling;

            child->sibling = newHead;
            child->parent = nullptr;
            newHead = child;

            child = next;
        }

        /// Create new heap from newHead
        BinomialHeap tempHeap(newHead);
        /// join the heaps and set its head as this->head
        this->head = this->join(tempHeap);
    }

    void extractMinimum() /// O(logN)
    {
        if (this->head == nullptr)
            return;

        dim--;

        Node *minim = this->head;
        Node *minPrev = nullptr;
        Node *next = minim->sibling;
        Node *nextPrev = minim;

        while (next != nullptr)
        {
            if (next->key < minim->key)
            {
                minim = next;
                minPrev = nextPrev;
            }

            nextPrev = next;
            next = next->sibling;
        }

        removeTreeRoot(minim, minPrev);
    }

    void erase(Node *node) /// O(logN)
    {
        decreaseKey(node, numeric_limits<int>::min());
        extractMinimum();
    }

public:

    size_t dim;

    BinomialHeap() : head(nullptr), dim(0) {
    }

    int top() const
    {
        return findMinimum();
    }

    void push(const int key)
    {
        this->insert(key);
    }

    void pop()
    {
        this->extractMinimum();
    }

    void merge(BinomialHeap& H)
    {
        this->head = this->join(H);
    }

    size_t size() const
    {
        return dim;
    }

    bool empty() const
    {
        return (dim == 0);
    }
};

int main() {

    freopen("algsort.in", "r", stdin);
    freopen("algsort.out", "w", stdout);

    int N;
    BinomialHeap B;

    cin >> N;

    for (int i = 0; i < N; ++i)
    {
        int A;
        cin >> A;
        B.push(A);
    }

    for (int i = 0; i < N; ++i)
    {
        cout << B.top() << " ";
        B.pop();
    }
}