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

}

猜你喜欢

转载自blog.csdn.net/u014449866/article/details/45850533