Prim用Java查找最小生成树的算法

时间:2020-02-23 14:41:41  来源:igfitidea点击:

最小生成树又称最小权重生成树是连接的,边缘加权的无向图的边缘的子集。
该子集将所有顶点连接在一起,没有任何循环并且具有最小可能的总边权重。

一个图可以有多个以上的最小生成树。
但是,对于同一棵树的不同MST,总成本将是相同的。

Prim算法

Prim的算法是一种贪婪算法,可以找到加权无向图的MST。

该算法通过从任意起始顶点一次建立一个MST来进行。
在每个步骤中,它都是最经济高效的选择。
即,它局部优化以实现全局最优。

Prim算法的工作方式如下:

  • 使用随机顶点(初始顶点)初始化最小生成树。

  • 找到将树连接到新顶点的所有边,找到最小值,然后将其添加到树中(贪婪的选择)。

  • 继续重复步骤2,直到得到最小的生成树(直到所有顶点都达到为止)。

我们可以看一个例子来了解Prim算法的工作原理。

令加权无向图如下:

我们选择0作为初始顶点。

下一步,我们从与MST连接的所有节点中选择最小值。

在随后的每个阶段,我们都找到将树连接到新顶点的最小成本边。

  • 边缘:0-1
  • 边缘:1-4
  • 边缘:4-2
  • 边缘:1-3

使用4条边线,我们已经连接了所有5个节点。
最小生成树的代价是所有边缘权重的总和。

在此示例中,它是:

4+1+6+2 = 13

Prim的算法Java代码

Java实现如下。

Graph类的代码:

package com.theitroad;
import java.util.*;
public class Graph
{
  
    //Representation of the graph 
    
  private static int infinite = 9999999;

  int[][]  LinkCost; //graph matrix
  int      num_nodes; //number of nodes 
  
  //constructor takes in a matrix as its input 
  Graph(int[][] mat)
  {
      int i, j;

      num_nodes = mat.length;

      LinkCost = new int[num_nodes][num_nodes];

      //copying the weights to LinkCost matrix
      for ( i=0; i < num_nodes; i++)
      {
          for ( j=0; j < num_nodes; j++)
          {
              LinkCost[i][j] = mat[i][j];

              if ( LinkCost[i][j] == 0 )
                  LinkCost[i][j] = infinite;
          }
      }
  }

  //function to get the nodes that are unreached
  public int unReached(boolean[] r)
  {
      boolean done = true;

      for ( int i = 0; i < r.length; i++ )
          if ( r[i] == false )
              return i;

      return -1;
  }

  public void Prim( )
  {
      int i, j, k, x, y;

      boolean[] Reached = new boolean[num_nodes];	//array to keep track of the reached nodes
      int[] predNode = new int[num_nodes];		//array to maintain min cost edge

//starting vertex
      Reached[0] = true;
      //setting other vertices as unreached
      for ( k = 1; k < num_nodes; k++ )
      {
          Reached[k] = false;
      }

      predNode[0] = 0;      //No edge for node 0

      printCoveredNodes( Reached );

   //we iterate for n-1 nodes that haven't been reached yet
      for (k = 1; k < num_nodes; k++)
      {
          x = y = 0;

          for ( i = 0; i < num_nodes; i++ )
              for ( j = 0; j < num_nodes; j++ )
              {
//update the MST with the minimum cost Link
                  if ( Reached[i] && !Reached[j] &&
                          LinkCost[i][j] < LinkCost[x][y] )
                  {
                      x = i;
                      y = j;
                  }
              }

          System.out.println("Next selected edge: (" +
                  + x + "," +
                  + y + ")" +
                  " cost = " + LinkCost[x][y]);

          predNode[y] = x;          //add the min cost link to predNode
          Reached[y] = true;

          printCoveredNodes( Reached );
          System.out.println();
      }

      printMinCostEdges( predNode );
  }
  //function to print the edges of spanning tree
  void printMinCostEdges( int[] a )
  {
 System.out.println("Edges in MST: ");
      for ( int i = 0; i < num_nodes; i++ )
          System.out.println( a[i] + " --> " + i );
  }

 
 void printCoveredNodes(boolean[] Reached )
  {
      System.out.print("Covered Nodes = ");
      for (int i = 0; i < Reached.length; i++ )
          if ( Reached[i] )
              System.out.print( i + " ");
      System.out.println();
  }

}

主类:

package com.theitroad;

public class Main {

  public static void main(String[] args) {
      int[][] conn = {{0, 4, 0, 0, 5},
              {4, 0, 3, 6, 1},
              {0, 3, 0, 6, 2},
              {0, 6, 6, 0, 7},
              {5, 1, 2, 7, 0},
      };

      Graph G = new Graph(conn);

      G.Prim();
  }
}