最短路径求算
来源:互联网 发布:黑苹果mac os安装教程 编辑:程序博客网 时间:2024/05/21 19:24
算法概述
Dijkstra 算法用于求算单源点最短路径问题,即给定源点,求算该点到其他各点的最短距离。
源点到任意点的最短路径建立在源点到该点前驱的最短路径上。以源点为中心,向外一步一步扩展,直到所有点的最短路径都被找出。
此外,该算法要求任意两点间的权值不可为负值。
情景
思路
一开始,我打算先实现Dijkstra 算法,所以直接将图的邻接矩阵、前驱数组这些设为全局变量(二维数组的传参我给忘了),而且将邻接矩阵直接初始化,减少调试的成本。
设源点为V0,求算V0到各终点的最短距离。
初始化最短距离数组(Distance)、前驱数组(Pioneer)、状态数组(S);
Dijikstra 算法核心:
1.从当前点开始更新最短距离数组(如果当前点是源点则不用更新,因为已经在初始化方法中更新了);
2.找出最短距离数组中权值最小的结点,并认为该点为已找到;
3.以该点作为当前点,回到第一步。
打印路径和最短距离;
代码一
#include<stdio.h>#include<stdlib.h>#define N 6 //记录图中点的数量#define MAX 1000#define START 0 //起点/*邻接矩阵寝室 0; 偏门 1; A广场 2; 大门 3; B广场 4; A 5;点与点间有临接路径,则值为两点间权值;点与点间没有临接路径,或为同点,则值为MAX;*/float Graph[N][N] = { { MAX,200,MAX,250,MAX,MAX }, { MAX,MAX,MAX,150,MAX,MAX }, { MAX,50,MAX,MAX,MAX,250 }, { MAX,MAX,MAX,MAX,60,MAX }, { MAX,MAX,300,MAX,MAX,MAX }, { MAX,MAX,250,MAX,350,MAX }};/*记录最短距离例如 V0 -> V2 -> V4 存在最短路径, 且V0 -> V2 = 20, V2 -> V4 = 40,则 Distance[4] = 60;Distance 数组元素初始化为START 行的数据;Distance[START] = 0;*/float Distance[N];/*记录前驱例如 V0 -> V2 -> V4 ,则Pioneer[4] = 2;Pioneer数组元素初始化全为 -1;Pioneer[起点] 永为 -1, 起点到起点没前驱;*/int Pioneer[N];/*记录起点与该点之间是否已找到最短路径;找到: 1, 没找到: 0;S 数组元素除起点外全部初始化为 0;S[起点] 永为 1;*/int S[N];/*************************************************//*初始化 Distance、Pioneer、S 数组*/void initialize() { //初始化Distance 数组 for (int i = 0;i < N;i++) { Distance[i] = Graph[START][i]; } Distance[START] = 0; //初始化Previous 数组 for (int i = 0;i < N;i++) { if (Distance[i] != 0 && Distance[i] != MAX) { Pioneer[i] = START; } else { Pioneer[i] = -1; } } //初始化S 数组 for (int i = 0;i < N;i++) { S[i] = 0; } S[START] = 1; //S[起点] 永为 1}/*迪吉斯特算法核心*/void Dijkstra() { int minV; float minDis = MAX; int curV = START; int count = 0; while (++count < N) { if (curV == START) { } else if (curV != START) { for (int i = 0;i < N;i++) { if (Graph[curV][i] != MAX && S[i] != 1) { if (Distance[i] > Graph[curV][i] + Distance[curV]) { Distance[i] = Graph[curV][i] + Distance[curV]; Pioneer[i] = curV; } } } //end for } for (int i = 0;i < N;i++) { if (Distance[i] < minDis && S[i] != 1) { minV = i; minDis = Distance[i]; } } //end for S[minV] = 1; //刷新 curV = minV; minDis = MAX; } //end while}/*打印路径*/void printPath() { //用于临时存放路径信息,帮助打印 //Path 数组元素默认值全为 -1; int Path[N]; //刷新Path 数组 for (int i = 0;i < N;i++) { Path[i] = -1; } //记录Path 的写入位置 //默认指向Path 数组的最后一个元素 int count = N - 1; int preV; int curV; int midian; //临时存放结点 for (int i = 0;i < N;i++) { count = N - 1; //排除起点 if (i == START) { continue; } Path[count--] = i; //终点 preV = Pioneer[i]; while (preV != -1) { Path[count--] = preV; curV = preV; preV = Pioneer[curV]; } count++; //打印路径 printf("%d -> %d 路径 : ", START, i); if (Distance[i] != MAX) { for (int j = count;j < N;j++) { printf("%d ", Path[j]); } printf("\n最短距离%6.2f", Distance[i]); } else { printf("\n不存在此路径"); } printf("\n"); }}/************************************************************/int main(){ initialize(); Dijkstra(); printPath(); system("pause"); return 0;}
代码二
修改之后,我将图邻接矩阵的初始化交由用户来处理,程序自动检测图的大小。
#include<stdio.h>#include<stdlib.h>#define SIZE 10 //记录图中点数量的最大值 #define MAX 1000#define START 0 //起点/*************************************************//*初始化图*/int InputGraph(float Graph[][SIZE]) { int cmd = 0; int VA; int VB; ///test int maxSize = 0; for (int i = 0;i < SIZE;i++) { for (int j = 0;j < SIZE;j++) { Graph[i][j] = MAX; } } puts("请输入指令 1:添加路径,0:退出"); scanf(" %d", &cmd); while (cmd != 0) { puts("请输入起点和终点,用空格分隔:"); scanf("%d %d", &VA, &VB); if (VA >= SIZE || VB >= SIZE) { puts("数组溢出"); } else { if (maxSize < VA) { maxSize = VA; } else if (maxSize < VB) { maxSize = VB; } puts("请输入两点间的距离:"); scanf("%f", &Graph[VA][VB]); if (Graph[VA][VB] < 0) { puts("错误距离"); } } puts("请输入指令 1:添加路径,0:退出"); scanf(" %d", &cmd); } maxSize++; return maxSize;}/*初始化 Distance、Pioneer、S 数组*/void initialize(float Graph[][SIZE], float Distance[], float Pioneer[], int S[], const int N) { //初始化Distance 数组 for (int i = 0;i < N;i++) { Distance[i] = Graph[START][i]; } Distance[START] = 0; //初始化Pioneer 数组 for (int i = 0;i < N;i++) { if (Distance[i] != 0 && Distance[i] != MAX) { Pioneer[i] = START; } else { Pioneer[i] = -1; } } //初始化S 数组 for (int i = 0;i < N;i++) { S[i] = 0; } S[START] = 1; //S[起点] 永为 1}/*迪吉斯特算法核心*/void Dijkstra(float Graph[][SIZE], float Distance[], float Pioneer[], int S[], const int N) { int minV; float minDis = MAX; int curV = START; int count = 0; while (++count < N) { if (curV == START) { } else if (curV != START) { for (int i = 0;i < N;i++) { if (Graph[curV][i] != MAX && S[i] != 1) { if (Distance[i] > Graph[curV][i] + Distance[curV]) { Distance[i] = Graph[curV][i] + Distance[curV]; Pioneer[i] = curV; } } } //end for } for (int i = 0;i < N;i++) { if (Distance[i] < minDis && S[i] != 1) { minV = i; minDis = Distance[i]; } } //end for S[minV] = 1; //刷新 curV = minV; minDis = MAX; }}/*打印路径*/void printPath(float Distance[], float Pioneer[],const int N) { //用于临时存放路径信息,帮助打印 //Path 数组元素默认值全为 -1; int Path[SIZE]; //刷新Path 数组 for (int i = 0;i < N;i++) { Path[i] = -1; } //记录Path 的写入位置 //默认指向Path 数组的最后一个元素 int count = N - 1; int preV; int curV; int midian; //临时存放结点 for (int i = 0;i < N;i++) { count = N - 1; //排除起点 if (i == START) { continue; } Path[count--] = i; //终点 preV = Pioneer[i]; while (preV != -1) { Path[count--] = preV; curV = preV; preV = Pioneer[curV]; } count++; //打印路径 printf("%d -> %d 路径 : ", START, i); if (Distance[i] != MAX) { for (int j = count;j < N;j++) { printf("%d ", Path[j]); } printf("\n最短距离%6.2f", Distance[i]); } else { printf("\n不存在此路径"); } printf("\n"); }}/************************************************************/int main(){ /* 邻接矩阵 寝室 0; 偏门 1; A广场 2; 大门 3; B广场 4; A 5; 点与点间有临接路径,则值为两点间权值; 点与点间没有临接路径,或为同点,则值为MAX; */ float Graph[SIZE][SIZE]; /* 记录最短距离 例如 V0 -> V2 -> V4 存在最短路径, 且V0 -> V2 = 20, V2 -> V4 = 40, 则 Distance[4] = 60; Distance 数组元素初始化为START 行的数据; Distance[START] = 0; */ float Distance[SIZE]; /* 记录前驱 例如 V0 -> V2 -> V4 ,则Pioneer[4] = 2; Pioneer 数组元素初始化全为 -1; Pioneer[起点] 永为 -1, 起点到起点没前驱; */ int Pioneer[SIZE]; /* 记录起点与该点之间是否已找到最短路径; 找到: 1, 没找到: 0; S 数组元素除起点外全部初始化为 0; S[起点] 永为 1; */ int S[SIZE]; const int N = InputGraph(Graph); initialize(Graph, Distance, Pioneer, S,N); Dijkstra(Graph, Distance, Pioneer, S, N); printPath(Distance, Pioneer, N); system("pause"); return 0;}
调试结果
最后,打印路径的那一部分程序可用递归函数的方式来处理,程序会更加简明。这个程序就先写到这儿吧,偷个懒。
阅读全文
0 0
- 最短路径求算
- BFS求迷宫的最短路径
- erl_stack_queue-队列求迷宫最短路径
- 【C++】递归求数组最短路径
- 求迷宫的最短路径
- 求迷宫的最短路径
- 图:求图的最短路径
- BFS循环求迷宫最短路径及路径数
- 最短路径 Dijksstra算法求最短路
- sdut 2622 最短路径(Dijkstra算法求最短路)
- HDU 3790 最短路径问题 【求花费最少的最短路径】
- 【图的最短路径】迪杰斯特拉算法求图的最短路径
- 求任意两个顶点间的最短路径
- 音乐播放基本 和 求文件最短路径
- 用haskell求图的最短路径!!!
- 求任意两点间的最短路径
- poj1024:Tester Program给出最短路径求对应迷宫
- 求校园最短路径的C++语言程序
- Linux内核移植(3)
- SSM框架实战系列之七_Spring框架
- 织梦dedecms修改include和plus重命名提高安全性防漏洞注入挂马
- 第一次测试,三四两题
- Akka(40): Http:Marshalling reviewed
- 最短路径求算
- 红黑树插入 删除演示过程
- 三栏自适应布局
- 经典美文诵读2 If I Were a Boy Again假如我又回到了童年
- 牛客练习赛7:B-购物 (dp)
- 重定位引入和链接脚本
- php dedecms将data这个文件夹移动到程序上一层目录
- Codeforces Round #449 (Div. 1) A. Nephren gives a riddle 模拟.
- 一张完整的死亡金属专辑发布,没错,从头到尾来自AI