构建最短路径迪杰斯特拉算法和弗洛伊德算法
解决有向带权图最短路径问题,选用迪杰斯特拉算法和普利姆算法。
迪杰斯特拉算法类似普利姆算法,也用到了贪心算法的思想,从局部最优解的全局最优解。是从确定的一点出发确定最小生成树。维护一个 path[] dist[] set[]。
弗洛伊德算法时间复杂度为O(n^3),可以获得任意一点到另一点的最小路径。需要维护一个 dist[][] 和 path[][]。
迪杰斯特拉算法分析如下: // 打印最短路径的方法 path[]采用双亲存储结构存了一棵二叉树
void printfPath(int path[], int a){ // 使用数组模拟 栈 int Stack[maxSize]; int top = -1; while (path[a] != -1){ stack[++top] = path[a]; // 找到自己的父节点 a = path[a]; } stack[++top] = a; // 打印最短路径 while (top != -1){ System.out.print(" " + stack[top--]); } } void dijkstra(MGraph g, int v, int dist[], int path[]){ int set[maxSize];//用于标记是否已经并入 for (int i = 0; i < g.n; i++){ dist[i] = g.edges[v][i]; set[i] = 0; if (g.edges[v][i] < INF){ path[i] = v; }else { // 没有直接相连时设置为 -1 path[i] = -1; } } set[v] = 1; path[v] = -1; int j; for(i = 0; i < g.n; i++){ min = INF; // 找出 dist[] 中最小的值并记录下标。(获取局部最优解) for(j = 0; j < g.n; j++){ if (set[j] == 0 && dist[j] < min){ u = j; min = dist[j] } } set[u] = 1; // 维护 dist[] for (j = 0; j < g.n; j++){ if (set[j] == 0 && dist[u] + g.edges[u][j] < dist[j]){ dist[j] = dist[u] + g.edges[u][j];
path[j] = u;//记录路径 } } } }
弗洛伊德算法思想较简单,就是选择中间点,三重循环遍历。
// 选取中间点 for (int k = 0; k < g.n; k++){ // 选择行号 for(int i = 0; i < g.n; i++){ // 选择列号 for(int j = 0; j < g.n; j++){ if (A[i][j] > A[i][k] + A[k][j]){ // 记录中间点 path[i][j] = k; A[i][j] = A[i][k] + A[k][j]; } } } }
欺骗自己最简单,欺骗自己最困难。
安慰自己最简单,安慰自己最困难。