Cod sursa(job #2753626)

Utilizator MirunaStefaniaLupascu Miruna-Stefania MirunaStefania Data 23 mai 2021 19:38:05
Problema Heapuri cu reuniune Scor 0
Compilator py Status done
Runda Arhiva educationala Marime 7.1 kb
import math

class FibonacciHeap:
    # internal node class
    class Node:
        def __init__(self, key, value):
            self.key = key
            self.value = value
            self.parent = self.child = self.left = self.right = None
            self.degree = 0
            self.mark = False

    # function to iterate through a doubly linked list
    def iterate(self, head):
        node = stop = head
        flag = False
        while True:
            if node == stop and flag is True:
                break
            elif node == stop:
                flag = True
            yield node
            node = node.right

    # pointer to the head and minimum node in the root list
    root_list, max_node = None, None

    # maintain total node count in full fibonacci heap
    total_nodes = 0

    # return min node in O(1) time
    def find_max(self):
        return self.max_node

    # extract (delete) the min node from the heap in O(log n) time
    # amortized cost analysis can be found here (http://bit.ly/1ow1Clm)
    def extract_max(self):
        z = self.max_node
        if z is not None:
            if z.child is not None:
                # attach child nodes to root list
                for child in self.iterate(z.child):
                    self.merge_with_root_list(child)
                    child.parent = None
            self.remove_from_root_list(z)
            # set new min node in heap
            if z == z.right:
                self.max_node = self.root_list = None
            else:
                self.max_node = z.right
                self.consolidate()
            self.total_nodes -= 1
        return z

    # insert new node into the unordered root list in O(1) time
    # returns the node so that it can be used for decrease_key later
    def insert(self, key, value=None):
        n = self.Node(key, value)
        n.left = n.right = n
        self.merge_with_root_list(n)
        if self.max_node is None or n.key > self.max_node.key:
            self.max_node = n
        self.total_nodes += 1
        return n

    # merge two fibonacci heaps in O(1) time by concatenating the root lists
    # the root of the new root list becomes equal to the first list and the second
    # list is simply appended to the end (then the proper min node is determined)
    def merge(self, h2):
        H = FibonacciHeap()
        H.root_list, H.max_node = self.root_list, self.max_node
        # fix pointers when merging the two heaps
        last = h2.root_list.left
        h2.root_list.left = H.root_list.left
        H.root_list.left.right = h2.root_list
        H.root_list.left = last
        H.root_list.left.right = H.root_list
        # update min node if needed
        if h2.max_node.key > H.max_node.key:
            H.max_node = h2.max_node
        # update total nodes
        H.total_nodes = self.total_nodes + h2.total_nodes
        return H

    # combine root nodes of equal degree to consolidate the heap
    # by creating a list of unordered binomial trees
    def consolidate(self):
        A = [None] * int(math.log(self.total_nodes) * 2)
        for x in self.iterate(self.root_list):
            d = x.degree
            while A[d] != None:
                y = A[d]
                if x.key < y.key:
                    temp = x
                    x, y = y, temp
                self.heap_link(y, x)
                A[d] = None
                d += 1
            A[d] = x
        # find new max node - no need to reconstruct new root list below
        # because root list was iteratively changing as we were moving
        # nodes around in the above loop
        for i in range(0, len(A)):
            if A[i] is not None:
                if A[i].key > self.max_node.key:
                    self.max_node = A[i]

    # actual linking of one node to another in the root list
    # while also updating the child linked list
    def heap_link(self, y, x):
        self.remove_from_root_list(y)
        y.left = y.right = y
        self.merge_with_child_list(x, y)
        x.degree += 1
        y.parent = x
        y.mark = False

    # merge a node with the doubly linked root list
    def merge_with_root_list(self, node):
        if self.root_list is None:
            self.root_list = node
        else:
            node.right = self.root_list.right
            node.left = self.root_list
            self.root_list.right.left = node
            self.root_list.right = node

    # merge a node with the doubly linked child list of a root node
    def merge_with_child_list(self, parent, node):
        if parent.child is None:
            parent.child = node
        else:
            node.right = parent.child.right
            node.left = parent.child
            parent.child.right.left = node
            parent.child.right = node

    # remove a node from the doubly linked root list
    def remove_from_root_list(self, node):
        if node == self.root_list:
            self.root_list = node.right
        node.left.right = node.right
        node.right.left = node.left

    # remove a node from the doubly linked child list
    def remove_from_child_list(self, parent, node):
        if parent.child == parent.child.right:
            parent.child = None
        elif parent.child == node:
            parent.child = node.right
            node.right.parent = parent
        node.left.right = node.right
        node.right.left = node.left


class Main:
    def __init__(self, input_file="mergeheap.in", output_file="mergeheap.out"):
        self.input_file = input_file
        self.output_file = output_file
        self.output = None
        self.heaps = {}

    def convert_array_to_int(self, arr):
        arr = arr.strip("\n ").split(" ")
        return list(map(lambda x: int(x), arr))

    def write_to_file(self, text):
        if not self.output:
            self.output = open(self.output_file, "a")

        self.output.write(str(text) + "\n")

    def start(self):
        file = open(self.input_file)
        first_line = file.readline()

        [N, Q] = self.convert_array_to_int(first_line)

        for i in range(Q):
            line = file.readline()
            args = self.convert_array_to_int(line)

            operation = args[0]

            if (operation == 1):
                heap_num = args[1]
                elem = args[2]

                if (not heap_num in self.heaps):
                    self.heaps[heap_num] = FibonacciHeap()
                    self.heaps[heap_num].insert(elem)
                else:
                    self.heaps[heap_num].insert(elem)

               

            elif operation == 2:
                heap_num = args[1]

                maximum = self.heaps[heap_num].extract_max()
                self.write_to_file(maximum.key)
            else:
                heap1 = args[1]
                heap2 = args[2]

                self.heaps[heap1] = self.heaps[heap1].merge(self.heaps[heap2])
                self.heaps.pop(heap2)
        file.close()

if __name__ == "__main__":
    main = Main()
    main.start()