Mini Shell

Direktori : /opt/imh-python/lib/python3.9/site-packages/pygraph/helpers/classes/
Upload File :
Current File : //opt/imh-python/lib/python3.9/site-packages/pygraph/helpers/classes/disjoint_set.py

"""Implements a Union/Find Disjoint Set class, used in other algorithms."""


class DisjointSet(object):
    """Implements an efficient disjoint set collection."""

    __label_counter = 0
    __set_counter = 0
    __forest = None

    def __init__(self):
        # We are using the implicit parent-pointer structure to store the trees
        self.__forest = {}

    def __len__(self):
        return self.__set_counter

    def __str__(self):
        return str(self.__forest)

    def add_set(self):
        """Adds a new set to the forest.
        Returns a label by which the new set can be referenced
        """
        self.__label_counter += 1
        new_label = self.__label_counter
        self.__forest[new_label] = -1  # All new sets have their parent set to themselves
        self.__set_counter += 1
        return new_label

    def find(self, node_label):
        """Finds the set containing the node_label.
        Returns the set label.
        """
        queue = []
        current_node = node_label
        while self.__forest[current_node] >= 0:
            queue.append(current_node)
            current_node = self.__forest[current_node]
        root_node = current_node

        # Path compression
        for n in queue:
            self.__forest[n] = root_node

        return root_node

    def union(self, label_a, label_b):
        """Joins two sets into a single new set.
        label_a, label_b can be any nodes within the sets
        """
        # Base case to avoid work
        if label_a == label_b:
            return

        # Find the tree root of each node
        root_a = self.find(label_a)
        root_b = self.find(label_b)

        # Avoid merging a tree to itself
        if root_a == root_b:
            return

        self.__internal_union(root_a, root_b)
        self.__set_counter -= 1

    def __internal_union(self, root_a, root_b):
        """Internal function to join two set trees specified by root_a and root_b.
        Assumes root_a and root_b are distinct.
        """
        # Merge the trees, smaller to larger
        update_rank = False
        # --Determine the larger tree
        rank_a = self.__forest[root_a]
        rank_b = self.__forest[root_b]
        if rank_a < rank_b:
            larger = root_b
            smaller = root_a
        else:
            larger = root_a
            smaller = root_b
            if rank_a == rank_b:
                update_rank = True
        # --Make the smaller tree a subtree of the larger tree
        self.__forest[smaller] = larger
        # --Update the rank of the new tree (if necessary)
        if update_rank:
            self.__forest[larger] -= 1

Zerion Mini Shell 1.0