Cod sursa(job #1419448)

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

using namespace std;

class BinomialHeap
{
public:

    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() : head(nullptr) {
    }

    BinomialHeap(Node* aux) : head(aux) {
    }

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

    bool empty() const
    {
        return (this->head == nullptr);
    }

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

    Node* mergeLists(BinomialHeap &heap1, BinomialHeap &heap2)
    {
        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(int key) /// O(logN)
    {
        Node *newNode = new Node(key);
        BinomialHeap tempHeap(newNode);
        this->head = this->join(tempHeap);
    }

    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 = join(tempHeap);
    }

    int extractMinimum() /// O(logN)
    {
        if (this->head == nullptr)
            return numeric_limits<int>::max();

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

        int a = minim->key;

        removeTreeRoot(minim, minPrev);

        return a;
    }

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

    void print(Node *r)
    {
        if (!r) return;

        cout << r->key << " ";

        print(r->sibling);
        print(r->child);
    }

    void print()
    {
        print(head);
    }

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

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.insert(A);
    }

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