Pagini recente » Cod sursa (job #1313037) | Cod sursa (job #311168) | Cod sursa (job #2798168) | Cod sursa (job #1909267) | Cod sursa (job #3126496)
#include <iostream>
#include <fstream>
#include <list>
#include <climits>
using namespace std;
ifstream in("mergeheap.in");
ofstream out("mergeheap.out");
struct Node{
int value, degree;
Node *parent, *child, *sibling;
};
Node* newNode(int value){
Node *aux = new Node;
aux->value = value;
aux->degree = 0;
aux->parent = nullptr;
aux->child = nullptr;
aux->sibling = nullptr;
return aux;
}
class BinomialHeap{
list<Node*> heap;
public:
Node* mergeHeap(Node* h1, Node* h2){
/// Nodul cu valoare mai mare va deveni parintele nodului cu valoarea mai mica
if(h1->value < h2->value){
swap(h1,h2);
}
h2->sibling = h1->child;
h2->parent = h1;
h1->child = h2;
h1->degree++;
return h1;
}
void heapsUnion(list<Node*> h2){
list<Node*> aux;
list<Node*>::iterator it1, it2;
it1 = heap.begin(); it2 = h2.begin();
/// Dupa ce dau merge la 2 noduri, pastrez rezultatul in prev pentru a verifica
/// daca ii pot da merge iarasi cu unul dintre nodurile curente
Node* prev = nullptr;
while(it1 != heap.end() && it2 != h2.end()){
if(prev){
if((*it1)->degree == (*it2)->degree && prev->degree){
aux.push_back(prev);
prev = nullptr;
continue;
} else if((*it1)->degree == prev->degree){
prev = mergeHeap(*it1, prev);
it1++;
continue;
} else if((*it2)->degree == prev->degree){
prev = mergeHeap(*it2, prev);
it2++;
continue;
} else {
aux.push_back(prev);
prev = nullptr;
continue;
}
}
/// Daca cele 2 noduri au acelasi grad, le dau merge. Daca nu, il bag pe cel
/// cu grad mai mic in aux si trec mai departe
if((*it1)->degree == (*it2)->degree){
prev = mergeHeap(*it1, *it2);
it1++; it2++;
} else if((*it1)->degree > (*it2)->degree){
aux.push_back(*it2);
it2++;
} else {
aux.push_back(*it1);
it1++;
}
}
/// Daca vreunul din cele 2 noduri a ramas neparcurs, aplic aceeasi procedura
/// ca mai sus pana nu mai are elemente neparcurse
while(it1 != heap.end()){
if(prev && (*it1)->degree == prev->degree){
prev = mergeHeap(*it1, prev);
it1++;
} else if(prev){
aux.push_back(prev);
prev = nullptr;
} else {
aux.push_back(*it1);
it1++;
}
}
while(it2 != h2.end()){
if(prev && (*it2)->degree == prev->degree){
prev = mergeHeap(*it2, prev);
it2++;
} else if(prev){
aux.push_back(prev);
prev = nullptr;
} else {
aux.push_back(*it2);
it2++;
}
}
if(prev){
aux.push_back(prev);
prev = nullptr;
}
heap = aux;
}
void push(int value){
/// Creem o lista auxiliara cu un singur nod si ii dam merge cu heapul mare
list<Node*> aux;
aux.push_back(newNode(value));
heapsUnion(aux);
}
int top(){
/// Returneaza maximul dintre noduri
int aux = INT_MIN;
for(Node* it: heap){
if(aux < it->value){
aux = it->value;
}
}
return aux;
}
void pop(){
int valMax = top();
Node* auxNode = nullptr;
list<Node*> aux;
list<Node*>::iterator it = heap.begin();
/// Stergem nodul cu valoare maxima din heap
while(it != heap.end()){
if((*it)->value == valMax){
auxNode = *it;
heap.remove(*it);
break;
} else {
it++;
}
}
/// Continuam doar daca nodul a fost gasit (heapul nu este deja gol)
if(!auxNode){
return;
}
/// Punem toti copiii nodului cu val maxima in aux
auxNode = auxNode->child;
while(auxNode){
aux.push_front(auxNode);
auxNode = auxNode->sibling;
}
/// Facem un union pentru a introduce la loc copiii nodului extras in heap
heapsUnion(aux);
}
/// Pentru a apela functia din main pentru cerinta 3, apelam functia aceasta intermediara
/// Functia apeleaza heapsUnion doar cu heap-ul dat ca parametru
void mergeH(BinomialHeap& h2){
heapsUnion(h2.heap);
}
};
int main(){
int n, q;
in >> n >> q;
BinomialHeap* heaps = new BinomialHeap[n];
int taskNo, heapNo, value, heap1, heap2;
for(int i = 0; i < q; i++){
in >> taskNo;
switch(taskNo){
case 1:
in >> heapNo >> value;
heaps[heapNo - 1].push(value);
break;
case 2:
in >> heapNo;
out << heaps[heapNo - 1].top() << endl;
heaps[heapNo - 1].pop();
break;
case 3:
in >> heap1 >> heap2;
heaps[heap1 - 1].mergeH(heaps[heap2 - 1]);
break;
}
}
}