一、 实验内容:
给定带权有向图G=(V,E),其中每条边的权都是非负数。给定一个起始顶点,称为源。计算从源到所有其他定点的最短路径长度,路径长度是各边权重之和。该问题称为单源最短路径问题。
基本思想:Dijkstra算法(迪杰斯特拉算法)是解单源最短路径问题的贪心算法。
算法思路:
1、选一顶点v为源点,并视从源点v出发的所有边为到各顶点的最短路径(确定数据结构:因为求的是最短路径,所以①就要用一个记录从源点v到其它各顶点的路径长度数组dist[],开始时,dist是源点v到顶点i的直接边长度,即dist中记录的是邻接阵的第v行。②设一个用来记录从源点到其它顶点的路径数组path[],path中存放路径上第i个顶点的前驱顶点)。
2、在上述的最短路径dist[]中选一条最短的,并将其终点(即<v,k>)k加入到集合s中。
3、调整T中各顶点到源点v的最短路径。 因为当顶点k加入到集合s中后,源点v到T中剩余的其它顶点j就又增加了经过顶点k到达j的路径,这条路径可能要比源点v到j原来的最短的还要短。调整方法是比较dist[k]+g[k,j]与dist[j],取其中的较小者。
4、再选出一个到源点v路径长度最小的顶点k,从T中删去后加入S中,再回去到第三步,如此重复,直到集合S中的包含图G的所有顶点。
二、 实验结果
三、实验分析与结论
定义源点为 0,dist[i]为源点 0 到顶点i的最短路径。其过程描述如下:
步骤 dist[1] dist[2] dist[3] dist[4] 已找到的集合
第1步 8 1 2 +∞ { 2 }
第2步 8 × 2 4 { 2, 3 }
第3步 5 × × 4 { 2, 3, 4 }
第4步 5 × × × { 2, 3, 4, 1 }
第5步 × × × × { 2, 3, 4, 1 }
Dijkstra 算法(中文名:迪杰斯特拉算法)是由荷兰计算机科学家 Edsger Wybe Dijkstra 提出。该算法常用于路由算法或者作为其他图算法的一个子模块。举例来说,如果图中的顶点表示城市,而边上的权重表示城市间开车行经的距离,该算法可以用来找到两个城市之间的最短路径。
四、源代码:
#include "stdafx.h"
#include <iostream>
using namespace std;
int matrix[100][100]; // 邻接矩阵
bool visited[100]; // 标记数组
int dist[100]; // 源点到顶点 i 的最短距离
int path[100]; // 记录最短路的路径
int source; // 源点
int vertex_num; // 顶点数
int edge_num; // 边数
void Dijkstra(int source)
{
memset(visited, 0, sizeof(visited)); // 初始化标记数组
visited[source] = true;
for (int i = 0; i < vertex_num; i++)
{
dist[i] = matrix[source][i];
path[i] = source;
}
int min_cost; // 权值最小
int min_cost_index; // 权值最小的下标
for (int i = 1; i < vertex_num; i++) // 找到源点到另外 vertex_num-1 个点的最短路径
{
min_cost = INT_MAX;
for (int j = 0; j < vertex_num; j++)
{
if (visited[j] == false && dist[j] < min_cost) // 找到权值最小
{
min_cost = dist[j];
min_cost_index = j;
}
}
visited[min_cost_index] = true; // 该点已找到,进行标记
for (int j = 0; j < vertex_num; j++) // 更新 dist 数组
{
if (visited[j] == false &&
matrix[min_cost_index][j] != INT_MAX && // 确保两点之间有边
matrix[min_cost_index][j] + min_cost < dist[j])
{
dist[j] = matrix[min_cost_index][j] + min_cost;
path[j] = min_cost_index;
}
}
}
}
int main()
{
cout << "请输入图的顶点数(<100):";
cin >> vertex_num;
cout << "请输入图的边数:";
cin >> edge_num;
for (int i = 0; i < vertex_num; i++)
for (int j = 0; j < vertex_num; j++)
matrix[i][j] = (i != j) ? INT_MAX : 0; // 初始化 matrix 数组
cout << "请输入边的信息(点 点 权):\n";
int u, v, w;//w:权
for (int i = 0; i < edge_num; i++)
{
cin >> u >> v >> w;
matrix[u][v] = matrix[v][u] = w;
}
cout << "请输入源点(<" << vertex_num << "):";
cin >> source;
Dijkstra(source);
for (int i = 0; i < vertex_num; i++)
{
if (i != source)
{
cout << source << " 到 " << i << " 的最短距离是:" << dist[i] << ",路径是:" << i;
int t = path[i];
while (t != source)
{
cout << "--" << t;
t = path[t];
}
cout << "--" << source << endl;
}
}
return 0;
}