The basic algorithm that programmers must know 7-Kruskal algorithm (Kruskal algorithm)

Kruskal algorithm

First understand what this algorithm is used for. The algorithm for
finding the minimum spanning tree is mainly Prim's algorithm and Kruskal algorithm, so it is the
Kruskal that uses the minimum spanning tree like the prim algorithm. Algorithm is an algorithm used to find the minimum spanning tree of a weighted connected graph.
Basic idea: select n-1 edges in the order of weight from small to large, and ensure that these n-1 edges do not form a loop

Problem background

A city has added 7 new stations (A, B, C, D, E, F, G), and now it is necessary to build roads to connect the 7
stations. The distance between each station is indicated by a border (right), for example, the distance between A and B is 12 kilometers
How to build roads to ensure that all stations can be connected, and the total mileage of roads to be built is the shortest?
Insert picture description here

solve

The idea of ​​Kruskal algorithm is this.
First, it sorts all the edges according to the weight from small to large,
and then selects one by one from the sorted edges to add to the minimum spanning tree. The
first step
is EF(2 ) to decide whether or not to form a loop, because E, F apex of the beginning of his or her own, so do not form a loop, it can be directly added to the array minimum spanning tree, set of vertices E F is
the second step
is selected to be CD (3 ), the vertices of C and D are all themselves, directly join, the vertices of C are D, the
third step is to
select the DE(4) edge, the vertices of D are D, the vertices of E are F, directly join, set D The vertex is E. The
fourth step is to
select CE. The vertex of C is D, the vertex of D is E, and the vertex of E is F, so the final vertex of C is F, and the vertex of E is also F. It forms a loop. It
is almost the same if you cannot join the following. Always traverse all edges once, and the minimum spanning tree is constructed

Code resolution

package basic;

import java.util.Arrays;

public class Kruskal
{
    
    
	//number表示边的个数
	public static int number;
	public static char[] nodes;
	public static final int INF=Integer.MAX_VALUE;
	public static int[][] weight;
	
 	public static void main(String[] args)
	{
    
    
 		weight= new int[][]{
    
    
 					/*A*//*B*//*C*//*D*//*E*//*F*//*G*/
 			/*A*/ {
    
       0,  12, INF, INF, INF,  16,  14},
 			/*B*/ {
    
      12,   0,  10, INF, INF,   7, INF},
 			/*C*/ {
    
     INF,  10,   0,   3,   5,   6, INF},
 			/*D*/ {
    
     INF, INF,   3,   0,   4, INF, INF},
 			/*E*/ {
    
     INF, INF,   5,   4,   0,   2,   8},
 			/*F*/ {
    
      16,   7,   6, INF,   2,   0,   9},
 			/*G*/ {
    
      14, INF, INF, INF,   8,   9,   0}}; 
 		nodes=new char[] {
    
    'A', 'B', 'C', 'D', 'E', 'F', 'G'};
 		kruskal(nodes, weight);
 		
	}
 	
 	public static void InitNumber()
 	{
    
    
 		for(int x=0;x<nodes.length;x++)
 		{
    
    
 			for(int y=x+1;y<nodes.length;y++)
 			{
    
    
 				if(weight[x][y]!=INF)
 				{
    
    
 					number++;
 				}
 			}
 		}
 	}
 	public static void kruskal(char[] nodes,int[][] weight)
 	{
    
    
 		//初始化number
 		InitNumber();
 		
 		//返回结果的索引index,和保存结果的数组result
 		int index=0;
 		Edge[] result=new Edge[nodes.length-1];
 		
 		//用于保存每一个节点在最小生成树中的结尾是什么
 		int[] ends=new int[number];	
 		
 		//然后想的是获取所有的边,然后将所有的边进行排序
 		Edge[] edges = getEdges();
 		Sort(edges);
 		
 		//然后是判断每一条边看看是否是需要加入到最小生成树上面的
 		for(int x=0;x<number;x++)
 		{
    
    
 			//然后现在想判断的是这条边的两个节点的顶点是不是同一个顶点
 			int end1 = GetEnd(ends, edges[x].start);
 			int end2 = GetEnd(ends, edges[x].end);
 			if(end1!=end2)
 			{
    
    
 				ends[end1]=end2;
 				result[index++]=edges[x];
 			}
 		}
		System.out.println("最小生成树为");
		for(int i = 0; i < index; i++) {
    
    
			System.out.println(result[i]);
		}
 	}
 	public static int GetEnd(int[] ends,char node)
 	{
    
    
 		int index=-1;
 		for(int x=0;x<nodes.length;x++)
 		{
    
    
 			if(nodes[x]==node)
 			{
    
    
 				index=x;
 				break;
 			}
 		}
 		while(ends[index]!=0)
 		{
    
    
 			index=ends[index];
 		}
 		return index;
 	}
 	
 	public static void Sort(Edge[] edges)
 	{
    
    
 		System.out.println("前:"+Arrays.toString(edges));
 		for(int x=0;x<edges.length-1;x++)
 		{
    
    
 			for(int y=0;y<edges.length-1-x;y++)
 			{
    
    
 				if(edges[y].weight>edges[y+1].weight)
 				{
    
    
 					Edge temp=edges[y];
 					edges[y]=edges[y+1];
 					edges[y+1]=temp;
 				}
 			}
 		}
 		System.out.println("后:"+Arrays.toString(edges));
 	}
 	
 	public static Edge[] getEdges()
 	{
    
    
 		int index=0;
 		Edge[] edges=new Edge[number];
 		for(int x=0;x<nodes.length;x++)
 		{
    
    
 			for(int y=x+1;y<nodes.length;y++)
 			{
    
    
 				if(weight[x][y]!=INF)
 				{
    
    
 					edges[index++]=new Edge(nodes[x], nodes[y], weight[x][y]); 					
 				}
 			}
 		}
 		return edges;
 	}
}
/*
 * 类Edge表示一条边,保存了start(边的开头字母),end(边的结尾字母),weight(边的权重)
 */
class Edge
{
    
    
	char start;
	char end;
	int weight;
	public Edge(char start, char end, int weight)
	{
    
    
		this.start = start;
		this.end = end;
		this.weight = weight;
	}
	@Override
	public String toString()
	{
    
    
		return "<" + start + "," + end + ">=" + weight;
	}
}

Guess you like

Origin blog.csdn.net/qq_43416157/article/details/108745970