这里讲一下Dijkstra算法在无向图中的简单使用.
下面给出一个无向图的示例:
要求出从V0到各个点的最短距离,可以使用Dijkstra算法(各边权值必须为正)。
具体地,我们讲解一下从V0到V5的最短路径。
首先找到从V0到V1和V2的距离,分别为5和3,去其中最短,并更新节点为节点2。
接着找与节点2相邻但是未访问过的节点(即V1,V3,V4),找出其中最短的距离并和原来的距离作比较,(例如,从V0到v2再到v1和原来从v0到v1作比较)。去其中最小的值,并更新节点。
重复以上步骤,知道找到到达V5的最短路径。
见下面:
最后得到最短路径是10。
下面给出C++代码(从V0到各个节点的最短路径)
#include <iostream>
#include <limits>
#define INF numeric_limits<int>::max()
using namespace std;
// 定义无向图的节点数最大值
const int MAX_NODES = 100;
// Dijkstra算法求解最短路径
void dijkstra(int graph[MAX_NODES][MAX_NODES], int n, int start)
{
int distances[MAX_NODES]; // 存储到各个节点的最短距离
bool visited[MAX_NODES]; // 标记节点是否已被访问
// 初始化
for (int i = 0; i < n; i++)
{
distances[i] = INF;
visited[i] = false;
}
distances[start] = 0; // 起始节点到自身的距离为0
for (int i = 0; i < n - 1; i++)
{
// 选择距离最短的节点作为当前节点
int curr = -1;
for (int j = 0; j < n; j++)
{
if (!visited[j] && (curr == -1 || distances[j] < distances[curr]))
{
curr = j;
}
}
if (curr == -1)
{
break; // 无法继续扩展无限大的节点
}
visited[curr] = true;
// 更新从当前节点到其他未访问节点的距离
for (int j = 0; j < n; j++)
{
if (!visited[j] && graph[curr][j] != INF)
{
distances[j] = min(distances[j], distances[curr] + graph[curr][j]);
}
}
}
// 打印最短距离
for (int i = 0; i < n; i++)
{
cout << "Distance from node " << start << " to " << i << ": ";
if (distances[i] == INF) {
cout << "uncontacted" << endl;
}
else {
cout << distances[i] << endl;
}
}
}
int main() {
int n = 6; // 图的节点数
int graph[MAX_NODES][MAX_NODES] =
{
{0, 5, 3, INF, INF, INF},
{5, 0, 2, 6, INF, INF},
{3, 2, 0, 7, 4, INF},
{INF, 6, 7, 0, 1, 2},
{INF, INF, 4, 1, 0, 6},
{INF, INF, INF, 2, 6, 0}
};
int start = 0; // 起始节点
dijkstra(graph, n, start);
return 0;
}
运行结果:
当然可以把上述代码转换称为MATLAB语法
function:
function dijkstra(graph, n, start)
INF = intmax('int32'); % 定义无穷大值
distances = ones(n, 1, 'int32') * INF; % 存储到各个节点的最短距离
visited = false(n, 1); % 标记节点是否已被访问
% 初始化
distances(start) = 0; % 起始节点到自身的距离为0
for i = 1:(n-1)
% 选择距离最短的节点作为当前节点
curr = -1;
for j = 1:n
if ~visited(j) && (curr == -1 || distances(j) < distances(curr))
curr = j;
end
end
if curr == -1
break; % 无法继续扩展无限大的节点
end
visited(curr) = true;
% 更新从当前节点到其他未访问节点的距离
for j = 1:n
if ~visited(j) && graph(curr, j) ~= INF
distances(j) = min(distances(j), distances(curr) + graph(curr, j));
end
end
end
% 打印最短距离
for i = 1:n
fprintf('Distance from node %d to %d: ', start, i);
if distances(i) == INF
fprintf('uncontacted\n');
else
fprintf('%d\n', distances(i));
end
end
end
main:
n = 6; % 图的节点数
INF = intmax('int32');
graph = [
0, 5, 3, INF, INF, INF;
5, 0, 2, 6, INF, INF;
3, 2, 0, 7, 4, INF;
INF, 6, 7, 0, 1, 2;
INF, INF, 4, 1, 0, 6;
INF, INF, INF, 2, 6, 0
]; % 图的邻接矩阵
start = 1; % 起始节点(MATLAB的索引从1开始)
dijkstra(graph, n, start);
由于我们是直接转换成的MATLAB语法,但是需要注意一些事项:
matlab语法数组索引是从1开始的,所以我们的start要从1开始,最后的输出,也应将i-1改成i。
当然可以使用graphshortestpath()函数直接得到答案:
n = 6; % 图的节点数
graph = [
0, 5, 3, inf, inf, inf;
5, 0, 2, 6, inf, inf;
3, 2, 0, 7, 4, inf;
inf, 6, 7, 0, 1, 2;
inf, inf, 4, 1, 0, 6;
inf, inf, inf, 2, 6, 0
]; % 图的邻接矩阵
start = 1; % 起始节点(MATLAB的索引从1开始)
target = 6; % 目标节点(MATLAB的索引从1开始)
[dist,path,pred] = graphshortestpath(sparse(graph), start, target);
disp('最短路径为:');
disp(path);
disp('最短距离为:');
disp(dist);
以上便是此算法的一些简单的内容。