最初看严蔚敏老师的《数据结构》一书时,便感觉Dijkstra (读作['daik stra])和Prim这两个算法几乎一摸一样,后来看到李清勇老师的《算法设计与问题求解》一书中对两中算法的比较,才知道两种算法的异同点。
关于Dijkstra的念法,请看如下地址说明:
https://www.cnblogs.com/daxia319/archive/2010/10/16/1853178.html
Dijkstra 算法是求连通图中起始点和每一个点之间的最短路径,而prim算法是求连通图的最小生成树,也就是生成树的最短路径之和。
假设图中所有顶点的集合为V,Dijkstra是先把起始顶点 u 0 u_0 u0加入集合S使得 S = { u 0 } S=\{u_0\} S={u0},然后从剩下的顶点集合V-S中寻找如下条件的最短的边:该边的一个顶点位于集合S,一个顶点位于集合V-S,这样一直循环直到所有的顶点V都在S中。
而Prim算法是在所有的边中寻找最短的边,同时如果该边的两个顶点都不在S中,就加入集合S,然后继续寻找其他的边,知道所有的顶点V都在集合S中。
在实现上,两者的思路基本一致,都要维护一个最短路径数组。在每次加入一个顶点后,都会计算并更新最短路径数组的每个下标值。所不同的是,Prim算法每次更新时,是将S集合中所有的顶点看作一个顶点A,计算的V-S 集合中顶点和顶点A的距离,而Dijkstra 是计算的起始点和新加入顶点的距离。
Dijkstra代码示例:
#include "dijkstra.h"#include "graph.h"//from 0
//plusint dijkstra(GRAPH * g) {int num = 0;unsigned __int64 * cost = new unsigned __int64[g->vertex];int * visit = new int[g->vertex];int* vertex = new int[g->vertex];int* v = new int[g->vertex];int idx = 0;for (int i = 0; i < g->vertex; i++) {idx = num * g->vertex + i;if (g->element[idx].e) {cost[i] = g->element[idx].e;}else {cost[i] = -1;}visit[i] = 0;vertex[i] = 0;v[i] = 0;}int pos = 1;for (num = pos; num < g->vertex; num++) {int n = 0; //must be in circleunsigned __int64 t = 0xffffffffffffffff; //must be in circlefor (int j = 0; j < g->vertex; j++){if (visit[j] == 0) {if (cost[j] < t) {t = cost[j];n = j;}}}//vertex[num] = n;v[num] = t;for (int k = 0; k < g->vertex; k++) {if (visit[n] == 0) {idx = n * g->vertex + k;int srcpos = num * g->vertex + k;if (g->element[idx].e && g->element[srcpos].e) {if (cost[k] > g->element[idx].e + g->element[srcpos].e) {cost[k] = g->element[idx].e + g->element[srcpos].e;vertex[k] = n;}}}}visit[n] = 1;}return 0;
}void testDijkstra() {GRAPH* g = genGraph(10,-1);dijkstra(g);return;
}
Prim代码示例:
#include "prim.h"#include "graph.h"int prim(GRAPH* g) {int num = 0;unsigned __int64* cost = new unsigned __int64[g->vertex];int* visit = new int[g->vertex];int* vertex = new int[g->vertex];int* v = new int[g->vertex];int idx = 0;for (int i = 0; i < g->vertex; i++) {idx = num * g->vertex + i;if (g->element[idx].e) {cost[i] = g->element[idx].e;}else {cost[i] = -1;}visit[i] = 0;vertex[i] = 0;v[i] = 0;}visit[0] = 1;vertex[0] = 0;v[0] = 0;int pos = 1;for (num = pos; num < g->vertex; num++) {int n = 0; //must be in circleunsigned __int64 t = 0xffffffffffffffff; //must be in circlefor (int j = 0; j < g->vertex; j++){if (visit[j] == 0) {if (cost[j] < t) {t = cost[j];n = j;}}}//vertex[num] = n;v[num] = t;for (int k = 0; k < g->vertex; k++) {if (visit[n] == 0) {idx = n * g->vertex + k;if (g->element[idx].e) {int srcpos = num * g->vertex + k;if (cost[k] > g->element[idx].e) {cost[k] = g->element[idx].e;vertex[k] = n;}}}}visit[n] = 1;}return 0;
}void testPrim() {GRAPH* g = genGraph(5, -1);prim(g);return;
}