1. 程式人生 > >Prim演算法與Dijkstra的異同

Prim演算法與Dijkstra的異同

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]+" ");
        }
    }

}