Cod sursa(job #2755398)

Utilizator izotova_dIzotova Daria izotova_d Data 27 mai 2021 08:37:31
Problema Heapuri cu reuniune Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.7 kb
#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;
}