Finding All Connected Components of an Undirected Graph

前端 未结 3 1725
栀梦
栀梦 2020-12-29 15:48

I have a list of objects (undirected edges) like below:

pairs = [

 pair:[\"a2\", \"a5\"],
 pair:[\"a3\", \"a6\"],
 pair:[\"a4\", \"a5\"],
 pair:[\"a7\", \"a         


        
3条回答
  •  不知归路
    2020-12-29 16:28

    The task you want to solve is best sovled with the algorithm of Disjoint Set Forest.

    Basically it is meant to solve exactly the problem you describe in optimal manner.

    • assign every vertex the set of vertices in which it belong. Let us denote it as root(v). Every such set will be considered as planted tree throughout the whole algorithm. Thus we will associate the root(v) with the root of the tree. So let's assume root(v) returns a vertex index.
    • The algorithm will go easiest if you keep throughout the algorithm one auxiliary array - the parent vertex of each vertex in its planted tree. If no such vertex exists we will store -1 instead to denote that. Thus you start the algorithm with parent[v] = -1 for each v as all vertices are initially in their own trees and you have no parents
    • We will also need one additional array that stores something that is called the rank of a vertex. It is basically equal to the depth of the subtree having the vertex as root. You need not worry too much about it. The array is used for performance optimizations. Lets name it rank. We initialize all ranks to 1s
    • You start processing the edges one by one and each edge might possibly trigger merge of trees. That is the interesting part in which you can optimise.

    Here is a pseudo code:

    parent[v] = -1 for v in Vertices
    rank[v] = 1 for v in Vertices
    root (v):
       processed = []
       while parent[v] != -1
          processed << v
          v = parent[v]
       for vertex : processed
          parent = v // optimisation: here we move the assoc. trees to be directly connected the root
       return v
    
    join (v1, v2):
      if rank[v1] < rank[v2]:
         parent[v1] = v2
      if rank[v1] > rank[v2]:
         parent[v2] = v1
      parent[v2] = v1
      rank[v1]++
    
    merge_trees (v1, v2)
      root1 = root(v1)
      root2 = root(v2)
      if root1 == root2:
        // already in same tree nothing else to be done here
        return true
      else
        // join trees
        join (v1, v2)
        return false
    
    main:
       numberTrees = size(Vertives)
       for edge: edges
          if merge_trees(edge.begin, edge.end):
             numberTrees--
       print numberTrees // this is the number you are interested in.
    

    NOTE If you are not intereseted too much in performace you can omit the rank thing. Without it your algorithm might run slower, but maybe it will be easier for you to understand and maintain. In this scenario you can join vertices in any direction. I should warn you that then there will exist scenarios that will trigger your algorithm to run slower.

提交回复
热议问题