Ring detection - parallel search set

First describe the idea, then list my own algorithm implementation, and finally list the code on geeksforgeeks for comparative analysis

thinking

In the process of parallel query, each time node i and node j are merged, their root nodes will be found in the parent array respectively

  • Merge if the root nodes are different
  • If it points to the same root node, it means that there are rings

Algorithm implementation

My version

    int[] unionParent = new int[V];

    int find(int node) {

        int result = node;
        while (unionParent[result] != -1) {
            result = unionParent[result];
        }

        // Compression path
        int tmp = node;
        while (unionParent[tmp] != -1) {
            tmp = unionParent[tmp];
            unionParent[tmp] = result;
        }

        return result;
    }

    boolean isCycle() {

        // init unionParent array
        for (int i = 0; i < V; i++) {
            unionParent[i] = -1;
        }

        // traversal edge
        for (int i = 0; i < V; i++) {
            Iterator<Integer> j = adj[i].iterator();
            while (j.hasNext()) {
                int subSet1 = find(i);
                int subSet2 = find(j.next());
                if (subSet1 != subSet2) {
                    unionParent[subSet2] = subSet1;
                }else {
                    // There is a ring
                    return true;
                }
            }

        }
        //Finish and check the collection
        return false;
    }

Geeks for geeks version

 // A utility function to find the subset of an element i
    int find(int parent[], int i)
    {
        if (parent[i] == -1)
            return i;
        return find(parent, parent[i]);
    }

    // A utility function to do union of two subsets
    void Union(int parent[], int x, int y)
    {
        int xset = find(parent, x);
        int yset = find(parent, y);
        parent[xset] = yset;
    }


    // The main function to check whether a given graph
    // contains cycle or not
    int isCycle( Graph graph)
    {
        // Allocate memory for creating V subsets
        int parent[] = new int[graph.V];

        // Initialize all subsets as single element sets
        for (int i=0; i<graph.V; ++i)
            parent[i]=-1;

        // Iterate through all edges of graph, find subset of both
        // vertices of every edge, if both subsets are same, then
        // there is cycle in graph.
        for (int i = 0; i < graph.E; ++i)
        {
            int x = graph.find(parent, graph.edge[i].src);
            int y = graph.find(parent, graph.edge[i].dest);

            if (x == y)
                return 1;

            graph.Union(parent, x, y);
        }
        return 0;
    }
  1. find is implemented recursively without compressing the path
  2. union does not judge whether the obtained xset and yset are equal. The comparison process is put in isCycle
  3. The find, union function parameter contains the parent array
  4. The parameter of isCycle is the Graph object, the parent array created in the function body

summary

I think in the version of geeks for geeks, the parameter setting is more reasonable and abstract

  1. I shouldn't declare the parent array in Graph
  2. isCycle should have a Graph object as a parameter. My version calls its own isCycle method every time it needs the corresponding Graph object

find function should be optimized for garbage compression

Posted on Fri, 20 Mar 2020 14:11:39 -0400 by crusty_php