1. 程式人生 > 實用技巧 >最小生成樹之克魯斯卡爾演算法

最小生成樹之克魯斯卡爾演算法

演算法思路

  1. 準備:邊類,圖類;
  2. 根據圖的鄰接矩陣獲得邊集合,並將邊按照邊的權值進行排序(升序);
  3. 依次取邊集合中的邊,如果取出來的這條邊不和已經選擇的邊構成迴路就新增這條邊,否則取邊集合中的下一條邊。

Q:怎麼判斷新取的邊和已經選取的邊會不會構成迴路?

A:引入一個數組,記錄每個頂點的終點,如果新取的這條邊的兩端的終點相同,說明構成迴路;否則不構成。

注:終點是指在最小生成樹中與它連通的最大頂點。

程式碼實現

package com.ex.kruskal;


import java.util.ArrayList;
import java.util.Collections;
import
java.util.List; public class Kruskal{
static final int INF=10000; // static class Edge implements Comparable<Edge>{ int p1; int p2; int weight; public Edge(int p1, int p2, int weight) { this.p1 = p1; this.p2 = p2; this
.weight = weight; } @Override public int compareTo(Edge o) { return this.weight-o.weight; } } // static class Graph{ char[] nodes; int[][] matrix; List<Edge> edges; public Graph(char[] nodes, int[][] matrix) {
this.nodes = nodes; this.matrix = matrix; generateEdges(); } //生成邊,並排序 public void generateEdges(){ edges=new ArrayList<>(); for (int i = 0; i < nodes.length; i++) { for (int j = i+1; j < nodes.length; j++) { if (matrix[i][j]!=INF) { edges.add(new Edge(i,j,matrix[i][j])); } } } Collections.sort(edges); } } //生成最小生成樹 public static void kruskal(Graph graph){ //準備 char[] nodes = graph.nodes; List<Edge> edges = graph.edges; int[][] matrix = graph.matrix; int[] ends=new int[nodes.length]; //每次選擇一個邊,如果不構成迴路就加入集合,否則下一條邊 for (int i = 0; i < edges.size(); i++) { Edge edge = edges.get(i); int end1 = getEnd(ends, edge.p1); int end2 = getEnd(ends, edge.p2); if (end1!=end2) { System.out.println(nodes[edge.p1]+"—>"+nodes[edge.p2]+":"+matrix[edge.p1][edge.p2]); ends[end1]=end2; } } } //獲得某個頂點的終點 private static int getEnd(int[] ends,int index){ while (ends[index]!=0){ index=ends[index]; } return index; } public static void main(String[] args) { char[] vertexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; //克魯斯卡爾演算法的鄰接矩陣 int matrix[][] = { { 0, 12, INF, INF, INF, 16, 14}, { 12, 0, 10, INF, INF, 7, INF}, { INF, 10, 0, 3, 5, 6, INF}, { INF, INF, 3, 0, 4, INF, INF}, { INF, INF, 5, 4, 0, 2, 8}, { 16, 7, 6, INF, 2, 0, 9}, { 14, INF, INF, INF, 8, 9, 0}}; //求最小生成樹 Graph graph = new Graph(vertexs, matrix); kruskal(graph); } }

普里姆演算法 VS 克魯斯卡爾演算法

                          n:結點數  E:邊數

演算法名 普里姆演算法 克魯斯卡爾演算法
時間複雜度 O(n2) O(ElogE)
適用範圍

稠密圖

(n、E相當)

稀疏圖

(E<<n)