普利姆演算法解決最短修路問題
普利姆演算法
1、應用場景-修路問題
2、最小生成樹
3、普利姆演算法介紹
4、普利姆演算法的最為簡單的理解(重點):
-
理論上7個點要6條路就可以連通,隨便從一個結點(村莊)出發(假設為A),先找該結點和鄰居結點(村莊)距離最小的結點(村莊),假設為B,最小路徑為A–>B ,這樣子A和B連通了。
把B加入已訪問的集合中,則為(A,B) -
找A的其他鄰居和B的其他鄰居,然後找到距離A或者B最小的那個鄰居結點,假設為C點,且路徑為B–>C最小,則A–>B B–>C 這樣A通過B可以走到C,即ABC連通了。把C加入已訪問的集合中,則為(A,B,C)
-
依次往後找,上一段為(A–>B B–>C),比較A,B,C的其他鄰居和A,B,C之間的距離,然後找到距離A或者B或者C最小的那個鄰居結點(村莊),假設為D點,且路徑為B–>D最小,則A–>B B–>C B–>D 這樣A通過B可以走到C,也可以走到D,即ABCD連通了。把D加入已訪問的集合中,則為(A,B,C,D)
…
-
依次迴圈,n節點需走n-1個次(eg:【點–點--點–點(4個結點(村莊)3條最小路徑便能連通)】),就能構建出一條理論上最短的連通路徑(有點貪心演算法的味道了,每次都取相鄰距離最小的點,並且把該點入集合,然後下次再把集合中那幾個點的相鄰的最小的點放入集合,把所有n個點放完也就n-1次,就構建了n-1條短路,n個村莊就能連起來互通了)
5、普利姆演算法最佳實踐(修路問題)
程式碼實現:
package com.czl.prim;
import java.lang.reflect.Array;
import java.util.Arrays;
public class PrimAlgorithm {
public static void main(String[] args) {
MinTree minTree = new MinTree();
//測試看看圖是否建立成功
char[] data = new char[] {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
//鄰接矩陣的關係使用二維陣列表示,10000這個大數,表示兩個點不連通
int[][] weight = {{10000, 5, 7, 10000, 10000, 10000, 2},
{5, 10000, 10000, 9, 10000, 10000, 3},
{7, 10000, 10000, 10000, 8, 10000, 10000},
{10000, 9, 10000, 10000, 10000, 4, 10000},
{10000, 10000, 8, 10000, 10000, 5, 4},
{10000, 10000, 10000, 4, 5, 10000, 6},
{2, 3, 10000, 10000, 4, 6, 10000}};
//得到MGraph物件
MGraph graph = minTree.createGraph(data, weight);
for (int[] link : graph.weight) {
System.out.println(Arrays.toString(link));
}
//測試普利姆演算法
minTree.prim(graph, 1);
}
}
//建立最小生成樹->村莊的圖
class MinTree {
/**
*
* @param data 圖的各個頂點的值
* @param weight 圖的鄰接矩陣
* @return
*/
public MGraph createGraph(char[] data, int[][] weight) {
MGraph graph = new MGraph(data.length);
graph.data = data;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data.length; j++) {
graph.weight[i][j] = weight[i][j];
}
}
return graph;
}
//普利姆演算法得到最小生成樹
/**
*
* @param mGraph 圖
* @param v 表示從圖的第幾個頂點開始生成 'A'->0 'B'->1 ...
*/
public void prim(MGraph mGraph, int v) {
//visited[] 標記結點(頂點)是否被訪問過。1為被訪問,0為沒訪問
int[] visited = new int[mGraph.verxs];
int minWeight = 10000;//初始化一個大數,後面在遍歷過程中,會被替換
//把當前這個結點標記為已訪問
visited[v] = 1;
//h1和h2記錄兩個頂點的下標
int h1 = -1;
int h2 = -1;
//有graph.verxs個頂點,普利姆演算法結束後,有graph.verxs-1條邊,因此這裡做graph,verxs-1次迴圈
/*
第一次迴圈,假設當前頂點為A,則尋找A相鄰頂點距離最小的頂點(村莊),假設為B ,且路徑為A --> B
此時子圖為A,B A-->B
第二次迴圈,比較A到其他相鄰頂點和B到其他相鄰頂點(村莊)的距離,找到最小距離的那個頂點(村莊), 假設為C 且路徑為B-->C最小 ,
此時子圖為 A,B ,C A-->B B-->C(即A可以通過B到達C)
第三次迴圈,比較A,B,C其他相鄰頂點的距離,找到最小距離的那個頂點,假設為D,且路徑為 B-->D
此時子圖為A,B,C,D A-->B B-->C B-->D(即A可以通過B到達D)
第四次迴圈,比較A,B,C,D其他相鄰頂點的距離,找到最小距離的那個頂點,假設為E,路徑為 D-->E
此時子圖為A,B,C,D,E A-->B B -->C B-->D D -->E (即A通過B到達D,再通過D到達E)
依次迴圈...
直到n個頂點遍歷n-1次後找到n個頂點(村莊)連線的最小路徑
*/
for (int k = 1; k < mGraph.verxs; k++) {
//確定每一次生成的子圖,與那個結點最近
//一次雙層for迴圈,可以找到子圖中已訪問的所有的點和其他相鄰頂點距離最小的頂點
for (int i = 0; i < mGraph.verxs; i++) {//i結點表示被訪問過的節點
for (int j = 0; j < mGraph.verxs; j++) {//j結點表示還沒訪問過的結點
//被訪問過的結點(visited[i] == 1 )和未訪問過的結點( visited[j] == 0 )之間的距離(權)<設定的minWeight(10000)
if (visited[i] == 1 && visited[j] == 0 && mGraph.weight[i][j] < minWeight) {
//替換minWeight(x尋找已經訪問過的結點和未訪問過的結點間的權值最小的邊)
minWeight = mGraph.weight[i][j];
h1 = i;
h2 = j;
}
}
}
//找到一條邊最小
System.out.println("邊<"+mGraph.data[h1]+","+mGraph.data[h2]+">權為:"+minWeight);
//將當前這個結點標記為已經訪問
visited[h2]=1;
//重新設定為最大值10000
minWeight = 10000;
}
}
}
//鄰接矩陣
class MGraph {
int verxs;//表示圖的結點個數
int weight[][];//存放邊,就是我們的鄰接矩陣
char[] data;//存放結點資料
public MGraph(int verx) {
verxs = verx;
weight = new int[verxs][verxs];
data = new char[verxs];
}
}
相關文章
- 普里姆(Prim)演算法演算法
- 使用A*演算法解迷宮最短路徑問題演算法
- 最短路徑問題 (dijkstra演算法)演算法
- 最小生成樹prim普里姆演算法演算法
- 遺傳演算法解決TSP問題演算法
- 最短路徑問題
- python實現Dijkstra演算法之 最短路徑問題Python演算法
- Bellmanford與Spfa解決存在負邊權的單源匯最短路問題
- bellman-ford 單源最短路問題 圖解圖解
- 單源最短路問題
- ACM日常訓練日記——8.8(二分dp,最小生成樹+克魯斯卡爾演算法和普利姆演算法)ACM演算法
- 遺傳演算法解決旅行商問題(TSP)演算法
- 修路
- 使用貪心演算法解決集合覆蓋問題演算法
- [最短路徑問題]Dijkstra演算法(含還原具體路徑)演算法
- 最小生成樹---普里姆演算法(Prim演算法)和克魯斯卡爾演算法(Kruskal演算法)演算法
- 遺傳演算法解決函式最佳化問題演算法函式
- HDU - 3790 (雙標準限制最短路徑)最短路徑問題
- 提問題比解決問題更重要
- week2 kuangbin 題單 最短路問題 + 並查集問題並查集
- 解決跨域問題跨域
- SERVICE問題解決方法
- 解決 Unexpectedlexicaldeclarationincaseblock的問題BloC
- 解決mapper重名問題APP
- qeephp 解決跨越問題PHP
- 解決高度塌陷問題
- P1354 房間最短路問題
- 九度oj-最短路徑問題
- 解決 github 訪問不了的問題Github
- 解決github訪問慢的問題Github
- 解決 Github 國內訪問問題Github
- 最短路演算法演算法
- No module named MYSQLdb 問題解決MySql
- rabbitmq解決erlang版本問題MQ
- 解決高度塌陷、定位問題
- display:flex解決的問題Flex
- As常見問題解決方法
- WebSocket跨域問題解決Web跨域