数据结构 18 图 最短路径-迪杰斯特拉最短算法
2014-01-03 20:01
387 查看
Dijkstra算法 最短路径算法
自己实现
Floyd 算法
自己的实现
唐老师的实现
#include <stdio.h> #include <stdlib.h> #define VNUM 5 #define MV 65536 // 比较直接和间接路径会不会变短 就是中转 int P[VNUM]; // 记录了前一个顶点的索引 int Dist[VNUM]; // 保存了顶点sv边的权值 int Mark[VNUM]; // 记录某个顶点是否被标记 int Matrix[VNUM][VNUM] = { {0, 10, MV, 30, 100}, {MV, 0, 50, MV, MV }, {MV, MV, 0, MV, 10 }, {MV, MV, 20, 0, 60 }, {MV, MV, MV, MV, 0 } }; void Dijkstra(int sv) // O(n*n) { int i = 0; int j = 0; if((0 <= sv) && (sv < VNUM)) { for(i = 0; i < VNUM; i++) // 初始化 { Dist[i] = Matrix[sv][i]; // 保存顶点的所有权值 P[i] = sv; // 保存顶点为sv Mark[i] = 0; // 设置所有顶点的状态为0 没有被标记 } Mark[sv] = 1; for(i = 0; i < VNUM; i++) // 遍历每个顶点 { int min = MV; int index = -1; for(j = 0; j < VNUM; j++) // 1.遍历这个顶点的所有边 找到某个未被标记的顶点边权值的最小值 并且标记这条边另外一个顶点作为新顶点 { if( !Mark[j] && (Dist[j]) < min ) { min = Dist[j]; index = j; // 这里的index表示原来顶点权值最小边对应的另外一个顶点的index 即新顶点 } } if( index > -1 ) { Mark[index] = 1; // 设置新顶点状态为1 标记 } for(j = 0; j < VNUM; j++) // 2.更新边的数组 { // 这里可以见算法精髓的那副三角图的关系 比较sv直接到j的大小和通过index顶点到j的大小 将较小值保存到Dist数组对应j位置 if( !Mark[j] && (min + Matrix[index][j] < Dist[j])) { Dist[j] = min + Matrix[index][j]; P[j] = index; // P记录了前一个顶点 设置P的j位置保存index } } } for(i = 0; i < VNUM; i++) { int p = i; printf("%d -> %d : %d\n", sv, p, Dist[p]); do { printf("%d <- ", p); p = P[p]; }while( p != sv ); printf("%d\n", p); } } } int main() { Dijkstra(0); return 0; }
自己实现
#include <stdio.h> #include <stdlib.h> #include "graph.h" #define SIZE 5 #define NOW 65536 int dist[SIZE]; // 记录了从某个顶点到各个顶点的最短路径 即权值 int visited[SIZE]; // 记录某个顶点是否被访问过 int record[SIZE]; // 记录访问过的最短路径节点 int matrix[SIZE][SIZE] = { {0, 10, NOW, 30, 100}, {NOW, 0, 50, NOW, NOW}, {NOW, NOW, 0, NOW, 10}, {NOW, NOW, 20, 0, 60}, {NOW, NOW, NOW, NOW, 0} }; void dijkstra(int vertex) { int i = 0; int j = 0; if(0 <= vertex && vertex < SIZE) { for(i = 0; i < SIZE; ++i) { dist[i] = matrix[vertex][i]; // 保存顶点vertex的所有权 visited[i] = 0; // 没有顶点被访问 record[i] = vertex; } visited[vertex] = 1; for(i = 0; i < SIZE; ++i) // 循环遍历每个节点 { int minWeight = NOW; int otherVertex = -1; // 1.知道vertex个的最小权 并且记录另外一个新连的节点 for(j = 0; j < SIZE; ++j) // 这里曾经把j误写成i 这个错误太难发现了 陷入死循环 { if(0 == visited[j] && dist[j] < minWeight) // 得到vertex的最小权 { minWeight = dist[j]; otherVertex = j; // 最小权对应的另外一个顶点 } } if(otherVertex > -1) { visited[otherVertex] = 1; // 标记新的顶点 } // 2.访问另外一个节点otherVertex 利用三角关系找到vertex到otherVertex最小权 即到第3个顶点的最小距离 for(j = 0; j < SIZE; ++j) { // vertex到index顶点相连的第3个顶点的距离 这是一个三角关系 if( (0 == visited[j]) && ((minWeight + matrix[otherVertex][j]) < dist[j]) ) { dist[j] = minWeight + matrix[otherVertex][j]; record[j] = otherVertex; } } } // 打印结果 for(i = 0; i < SIZE; ++i) { int p = i; printf("%d -> %d : %d\n", vertex, p, dist[p]); // 打印从vertex到各个顶点的最短距离 do { printf("%d <- ", p); p =record[p]; }while(p != vertex); printf("%d\n", p); } } } int main() { dijkstra(0); return 0; }
Floyd 算法
自己的实现
#include <stdio.h> #include <stdlib.h> #include "graph.h" #define SIZE 5 #define NOW 65536 int record[SIZE][SIZE]; // 记录两个顶点间经过的中间节点 初始化为第二个节点 int visited[SIZE][SIZE]; // 记录两个顶点间的权 int matrix[SIZE][SIZE] = { {0, 10, NOW, 30, 100}, {NOW, 0, 50, NOW, NOW}, {NOW, NOW, 0, NOW, 10}, {NOW, NOW, 20, 0, 60}, {NOW, NOW, NOW, NOW, 0} }; void floyd() { int i = 0; int j = 0; int k = 0; // 1.初始化 visited保存了 所有路径的权 record保存了最小权 for(i = 0; i < SIZE; ++i) { for(j = 0; j < SIZE; ++j) { visited[i][j] = matrix[i][j]; record[i][j] = j; } } // 2.中转 for(i = 0; i < SIZE; ++i) { for(j = 0; j < SIZE; ++j) { for(k = 0; k < SIZE; ++k) { if(visited[j][i] + visited[i][k] < visited[j][k]) // j-i-k < j-k 核心就是中转的思维 { visited[j][k] = visited[j][i] + visited[i][k]; record[j][k] = record[j][i]; // 将i保持到其中 用于打印 } } } } // 3.打印 for(i = 0; i < SIZE; ++i) { for(j = 0; j < SIZE; ++j) { int p = -1; printf("%d -> %d : %d \n", i, j, visited[i][j]); printf("%d", i); p = i; do { p = record[p][j]; // 得到p-j的中间节点 继续打印出全部经过的节点 printf("-> %d", p); }while(p != j); // 因为初始值为j printf("\n"); } } } int main() { floyd(); return 0; }
唐老师的实现
#include <stdio.h> #include <stdlib.h> #define VNUM 5 #define MV 65536 // 比较直接和间接路径会不会变短 就是中转 int P[VNUM][VNUM]; // 记录了顶点的索引 int A[VNUM][VNUM]; int Matrix[VNUM][VNUM] = { {0, 10, MV, 30, 100}, {MV, 0, 50, MV, MV }, {MV, MV, 0, MV, 10 }, {MV, MV, 20, 0, 60 }, {MV, MV, MV, MV, 0 } }; void Floyd() // O(n*n*n) { int i = 0; int j = 0; int k = 0; for(i = 0; i < VNUM; i++) // 初始化 { for(j = 0; j < VNUM; j++) { A[i][j] = Matrix[i][j]; P[i][j] = j; // 从i 到 j的最短路径 第二个顶点的值 } } for(i = 0; i < VNUM; i++) // 思想就是中转 每一个顶点都拿来中转 { for(j = 0; j < VNUM; j++) { for(k = 0; k < VNUM; k++) { if( (A[j][i] + A[i][k]) < A[j][k] ) // 中转后小于原来的值 j->i + i->k < j->k { A[j][k] = A[j][i] + A[i][k]; // 更新 P[j][k] = P[j][i]; } } } } for(i = 0; i < VNUM; i++) // 打印 { for(j = 0; j < VNUM; j++) { int p = -1; printf("%d -> %d : %d\n", i, j, A[i][j]); printf("%d", i); p = i; do { p = P[p][j]; printf(" -> %d", p); } while (p != j); printf("\n"); } } } int main() { Floyd(); return 0; }
相关文章推荐
- 数据结构之 迪杰斯特拉最短路径算法
- 经典算法——迪杰斯特拉(Dijkstra)最短路径
- 理解最短路径——迪杰斯特拉(dijkstra)算法
- 单源最短路径长度Dijkstra(迪杰斯特拉)算法
- 最短路径之迪杰斯特拉(Dijkstra)算法
- 迪杰斯特拉-最短路径算法
- 数据结构之---C语言实现最短路径之Dijkstra(迪杰斯特拉)算法
- 理解最短路径——迪杰斯特拉(dijkstra)算法
- 数据结构看书笔记(十)—— 求最短路径问题之--迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法
- 最短路径顶点算法:最短路径之迪杰斯特拉(Dijkstra)算法Strut2教程-java教程
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 【图】最短路径--迪杰斯特拉(Dijkdtra)算法
- [转]最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径问题 迪杰斯特拉(Dijkstra)算法
- Java实现求最短路径算法——————Dijkstra(迪杰斯特拉)
- 最短路径算法(1)—Dijkstra(迪杰斯特拉)算法
- Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例
- [数据结构]--图(图的遍历,最小生成树,最短路径算法)
- 数据结构_图_最短路径_狄杰斯特拉(Dijkstra)算法