Pagini recente » Cod sursa (job #927558) | Cod sursa (job #484389) | Cod sursa (job #2815526) | Cod sursa (job #1989571) | Cod sursa (job #2755398)
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
using namespace std;
ifstream fin("mergeheap.in");
ofstream fout("mergeheap.out");
struct Node {
int value;
int degree;
Node* parent;
Node* sibling;
Node* child;
};
Node* createNewNode(int key)
{
Node* temp = new Node;
temp->value = key;
temp->degree = 0;
temp->parent = temp->sibling = temp->child = nullptr;
return temp;
}
//class of binomial heap
class Binomial_Heap {
//all the roots are connected with linked list
list<Node*> heap;
public:
list<Node*> getHeap() { return this->heap; }
void mergeTrees(Node* root1, Node* root2)
{
if (root1->value < root2->value)
{
swap(*root1, *root2);
}
root2->parent = root1;
root2->sibling = root1->child;
root1->child = root2;
root1->degree += 1;
}
void adjust()
{
if (heap.size() <= 1)
{
return;
}
list <Node*> ::iterator precedent, current, next;
//setting the positions
current = precedent = heap.begin();
current++;
next = current;
next++;
while (current != heap.end())
{
/*
Condition for merging trees. We set up three pointers: precedent, current and next.
That way the trees with the same degree will be merged only if its last two trees
or the degree of next one is bigger.
For example: 1-2 3-4 5-6 7-8-9-10. Instead of merging 1-2 and 3-4 we will merge 3-4 and 5-6.
*/
while ((next == heap.end() || (*next)->degree > (*current)->degree) && current != heap.end() && (*precedent)->degree == (*current)->degree)
{
mergeTrees((*current), (*precedent));
list<Node*> ::iterator position = precedent;
if (precedent == heap.begin())
{
precedent++;
current++;
if (next != heap.end())
next++;
}
else
{
precedent--;
}
heap.erase(position);
}
precedent++;
if (current != heap.end())
{
current++;
}
if (next != heap.end())
{
next++;
}
}
}
void insert_key(int key)
{
Node* new_node = createNewNode(key);
heap.push_front(new_node);
adjust();
}
void heap_union(list<Node*> second_heap)
{
//Sorting by degree, so that the biggest degree is in the end.
list<Node*> final_one;
list<Node*> ::iterator position1, position2;
position1 = heap.begin();
position2 = second_heap.begin();
while (position1 != heap.end() && position2 != second_heap.end())
{
if ((*position1)->degree < (*position2)->degree)
{
final_one.push_back((*position1));
position1++;
}
else
{
final_one.push_back((*position2));
position2++;
}
}
while (position1 != heap.end())
{
final_one.push_back((*position1));
position1++;
}
while (position2 != second_heap.end())
{
final_one.push_back((*position2));
position2++;
}
heap = final_one;
adjust();
}
void deleteMaxim(Node* to_delete,list<Node*> ::iterator pos)
{
if (to_delete->degree == 0)
{
fout << to_delete->value << "\n";
heap.erase(pos);
return;
}
fout << to_delete->value << "\n";
list<Node*> new_heap;
new_heap.push_front((*pos)->child);
Node* sibl = (*pos)->child;
sibl->parent = nullptr;
while (sibl->sibling != nullptr)
{
new_heap.push_front(sibl->sibling);
sibl->parent = nullptr;
sibl = sibl->sibling;
}
heap.erase(pos);
heap_union(new_heap);
}
void findMaxim()
{
list<Node*> ::iterator maxim = heap.begin();
list<Node*> ::iterator maxim_pos = heap.begin();
Node* temp = (*maxim);
for (maxim = heap.begin(); maxim != heap.end(); maxim++)
{
if ((*maxim)->value > temp->value)
{
temp = (*maxim);
maxim_pos = maxim;
}
}
deleteMaxim(temp,maxim_pos);
}
};
/*
void heapify(vector<int> to_heap, Binomial_Heap& BH)
{
for (int i = 0; i < to_heap.size(); i++)
{
BH.insert_key(to_heap[i]);
}
}
*/
int main()
{
Binomial_Heap BH[101];
int n, m;
int operation;
int index, value;
int index1, index2;
fin >> n >> m;
for (int i = 0; i < m; i++)
{
fin >> operation;
if (operation == 1)
{
fin >> index >> value;
BH[index].insert_key(value);
}
else if (operation == 2)
{
fin >> index;
BH[index].findMaxim();
}
else
{
fin >> index1 >> index2;
BH[index1].heap_union(BH[index2].getHeap());
Binomial_Heap BH_temp;
BH[index2] = BH_temp;
}
}
return 0;
}