Pagini recente » Monitorul de evaluare | Cod sursa (job #1057631) | Cod sursa (job #635034) | Cod sursa (job #1069720) | Cod sursa (job #1419448)
#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() << " ";
}