Prim演算法與Dijkstra的異同
阿新 • • 發佈:2019-01-02
prim演算法和Dijkstra演算法都是圖論或者離散數學裡面的典型演算法,由於兩者在實現策略上有很多相似之處,現做以比較:
同:
(1)、兩者都屬於貪心演算法的應用;
(2)、都使用了堆結構;
(3)、都有鬆弛操作;
異:
(1)、給一堆村子之間修路,保證花費最小,用prim演算法;
從一個村子到其他所有村子修路,並且希望花費最小,用Dijkstra。
(2)、prim適用於無相連通圖;Dijkstra則適用於有向圖;
(3)、鬆弛條件不一樣:prim是從S到V-S進行鬆弛(V是所有節點集合,S是加入最小生成樹的集合);而Dijkstra的鬆弛操作是從單源點到其他所有節點的鬆弛。
Prim演算法:
資料結構:
int[] adjvex = new int[MAXVEX];//每一個節點的鄰接節點
int[] lowcost = new int[MAXVEX];//當前S到V-S的最短開銷
鬆弛操作:
if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j]){
lowcost[j] = G.arc[k][j];
adjvex[j] = k;
}
程式碼:
package graph;
public class prim {
static final int INF = 9999;
static final int MAXVEX = 9;
class MGraph{
int numVertexes = 9;
private int[][] arc = {
{0,10,INF,INF,INF,11,INF,INF,INF},
{10,0,18,INF,INF,INF,16,INF,12},
{INF,INF,0,22,INF,INF,INF,INF,8},
{INF,INF,22 ,0,20,INF,INF,16,21},
{INF,INF,INF,20,0,26,INF,7,INF},
{11,INF,INF,INF,26,0,17,INF,INF},
{INF,16,INF,INF,INF,17,0,19,INF},
{INF,INF,INF,16,7,INF,19,0,INF},
{INF,12,8,21,INF,INF,INF,INF,0}
};
}
public static void main(String[] args){
MGraph G = new prim().new MGraph();//內部類的呼叫不同於其他類
MiniSpanTree_prim(G);
}
static void MiniSpanTree_prim(MGraph G){
int min,i,j,k;
int[] adjvex = new int[MAXVEX];//每一個節點的鄰接節點
int[] lowcost = new int[MAXVEX];//當前S到V-S的最短開銷
lowcost[0] = 0;//v0加入生成樹
adjvex[0] = 0;//S集合中0與0不臨接
for(i = 1;i < G.numVertexes;i++){//初始化設定邊界
lowcost[i] = G.arc[0][i];
adjvex[i] = 0;//初始狀態S中只有v0,其它均不鄰接
}
for(i = 1;i < G.numVertexes;i++){
min = INF;
j = 1; k = 0;
while(j < G.numVertexes)//迴圈全部節點,每次只選最小的
{
if(lowcost[j] != 0 && lowcost[j] < min)//不到沒加入S而且還可以經過更短的路到達
{
min = lowcost[j];
k = j;
}
j++;
}
System.out.print("("+adjvex[k]+","+k+")");
lowcost[k] = 0;//把這個到S最小的點加入S
for(j = 1;j < G.numVertexes;j++){//既然下標為k的節點加入了,那麼就要更新lowcost陣列
if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j]){
lowcost[j] = G.arc[k][j];
adjvex[j] = k;
}
}
}
for(i = 0;i < G.numVertexes;i++)
{
System.out.print(lowcost[i]+" ");
}
System.out.print("\n");
for(i = 0;i < G.numVertexes;i++)
{
System.out.print(adjvex[i]+" ");
}
}
}
DijkStra演算法:
資料結構:
boolean[] visit = new boolean[MAXVEX];//用來記錄是否到達過某節點
int[] dist = new int[MAXVEX];//用來記錄單原點到其它節點路徑
鬆弛操作:
if(!visit[j] && dist[j] > dist[k] + G.arc[k][j])//鬆弛
{
dist[j] = dist[k] + G.arc[k][j];
}
程式碼:
package graph;
public class Dijkstra {
static final int INF = 999999;
static final int MAXVEX = 9;
class MGraph{
int numVertex = 9;
int[][] arc = {
{0,1,5,INF,INF,INF,INF,INF,INF},
{1,0,3,7,5,INF,INF,INF,INF},
{5,3,0,INF,1,7,INF,INF,INF},
{INF,7,INF,0,2,INF,3,INF,INF},
{INF,5,1,2,0,3,6,9,INF},
{INF,INF,7,INF,3,0,INF,5,INF},
{INF,INF,INF,3,6,INF,0,2,7},
{INF,INF,INF,INF,9,5,2,0,4},
{INF,INF,INF,INF,INF,INF,7,4,0}
};
}
public static void main(String[] args){
shortestPath(new Dijkstra().new MGraph());
}
public static void shortestPath(MGraph G){
boolean[] visit = new boolean[MAXVEX];//用來記錄是否到達過某節點
int[] dist = new int[MAXVEX];//用來記錄單原點到其它節點路徑
int min;
int j,i,k = 0;
for(i = 1;i < G.numVertex;i++){
visit[i] = false;
dist[i] = G.arc[0][i];//前驅結點只有v0
}
visit[0] = true;
dist[0] = 0;
for(i = 1;i < G.numVertex;i++){
min = INF;
for(j = 0;j < G.numVertex;j++)
{
if(!visit[j] && dist[j] < min)
{
k = j;
min = dist[j];
}
}
visit[k] = true;//將節點Vk加入S
System.out.print(k+" ");
for(j = 0;j < G.numVertex;j++){//更新V0到其它節點的最短路徑
if(!visit[j] && dist[j] > dist[k] + G.arc[k][j])//鬆弛
{
dist[j] = dist[k] + G.arc[k][j];
}
}
}
System.out.print("\n");
for(i = 0;i < G.numVertex;i++){
System.out.print(dist[i]+" ");
}
}
}