Pagini recente » Cod sursa (job #2348381) | Cod sursa (job #59534) | Cod sursa (job #1850495) | Cod sursa (job #2368209) | Cod sursa (job #2749157)
#include <iostream>
#include <fstream>
#include <list>
using namespace std;
ifstream f("mergeheap.in");
ofstream g("mergeheap.out");
struct Nod {
int val, grad;
Nod* copil, * frate, * parinte;
};
Nod* newNod(int x) { //se creeaza un nod nou
Nod* newNod = new Nod;
newNod->grad = 0;
newNod->val = x;
newNod->copil = NULL;
newNod->frate = NULL;
newNod->parinte = NULL;
return newNod;
}
class BinomialHeap {
list <Nod*> heap;
public:
void deleteRadacina(Nod* min) { //se elimina radacina unui tree si se "distribuie" copii in heap
if (min->grad == 0) {
delete min;
return;
}
Nod* del = min;
min->copil->parinte = NULL;
heap.push_front(min->copil);
min = min->copil;
while (min->frate) {
min->frate->parinte = NULL;
heap.push_front(min->frate);
min = min->frate;
}
delete del;
}
Nod* mergeTrees(Nod* t1, Nod* t2) { //se merge-uiesc 2 binary trees
if (t1->val < t2->val) {
Nod* aux;
aux = t1;
t1 = t2;
t2 = aux;
}
t2->frate = t1->copil;
t1->copil = t2;
t2->parinte = t1;
t1->grad++;
return t1;
}
void reHeap() { //se repara proprietatea de binomial heap, adica se unesc toti arborii care au acelasi grad
list <Nod*> ::iterator pred, curr, next, del;
if (heap.size() <= 1)
return;
pred = heap.begin();
curr = pred;
curr++;
next = curr;
if (next != heap.end())
next++;
while (curr != heap.end()) {
if ((*pred)->grad < (*curr)->grad) { //daca arborii au grad diferit => nu se pot uni
pred++;
curr++;
if (next != heap.end())
next++;
}
else if ((*pred)->grad == (*curr)->grad) { //daca arborii curenti au acelasi grad
if (next != heap.end() && ((*pred)->grad == (*next)->grad)) { //daca si arborele urmator are acelasi grad vrem sa avansam, pentru a le uni pe ultimele 2
pred++;
curr++;
next++;
}
else { //altfel, se unesc arborii curenti
*pred = mergeTrees(*pred, *curr);
del = curr; //se sterge arborele 2 dupa ce se avanseaza pozitia
curr++;
heap.erase(del);
if (next != heap.end())
next++;
}
}
}
}
void meld(BinomialHeap& heap2) { //se meld-uieste un binomial heap la binomial heap-ul curent
list <Nod*> ::iterator h1 = heap.begin();
list <Nod*> ::iterator h2 = heap2.heap.begin();
list <Nod*> newHeap;
//algoritm de interclasare, in functie de gradurile arborilor din fiecare heap
while (h1 != heap.end() && h2 != heap2.heap.end()) {
if ((*h1)->grad <= (*h2)->grad) {
newHeap.push_back(*h1);
h1++;
}
else {
newHeap.push_back(*h2);
h2++;
}
}
while (h1 != heap.end()) {
newHeap.push_back(*h1);
h1++;
}
while (h2 != heap2.heap.end()) {
newHeap.push_back(*h2);
h2++;
}
heap = newHeap; //se pune heap-ul rezultat in binomial heap-ul #1
reHeap(); // se ruleaza algoritmul care uneste arborii de acelasi grad pe heap-ul rezultat
heap2.heap.clear(); //se sterge binomial heap-ul #2
}
list <Nod*> ::iterator getRadacina() { //se returneaza nodul care contine minimul
list <Nod*> ::iterator itm;
Nod* min = newNod(-999999999);
for (list <Nod*> ::iterator it = heap.begin(); it != heap.end(); it++) {
if ((*it)->val > min->val) {
min = *it;
itm = it;
}
}
return itm;
}
int top() {
return (*getRadacina())->val;
}
void push(int x) {
Nod* newTree = newNod(x);
heap.push_front(newTree);
reHeap();
}
void pop() {
list <Nod*> ::iterator radacina = getRadacina();
BinomialHeap newHeap; //se creeaza un heap nou
newHeap.deleteRadacina(*radacina); //se pun copii tree-ului care contine minimul in heap-ul nou
heap.erase(radacina); //se sterge tree-ul care contine minimul din heap
meld(newHeap); //se insereaza copii tree-ului in heap
}
};
int N, M;
BinomialHeap Heap[101];
int main()
{
f >> N >> M;
int task, h, x, h1, h2;
for (int i = 1; i <= M; ++i) {
f >> task;
if (task == 1) {
f >> h >> x;
Heap[h].push(x);
}
if (task == 2) {
f >> h;
g << Heap[h].top() << '\n';
Heap[h].pop();
}
if (task == 3) {
f >> h1 >> h2;
Heap[h1].meld(Heap[h2]);
}
}
return 0;
}