1. 算法原理
参考此篇足矣:
Dijkstra算法图文详解
2. C++ 实现
问题描述:
有四个节点( 0,1, 2, 3),已知 0和1之间的距离为3米, 1和2之间的距离为4米,2和3之间的距离为2米, 0和3之间的距离为5米。
求:1 --> 3的最短距离是多少?
思路:采用邻接矩阵法,通过二维vector保存相邻节点的距离,其中:自节点距离为0,不相连节点的距离初始化为一个很大的值INF
vector<vector<int>> global_map = { // 纵坐标为起点,横坐标向为终点
/*0*/ /*1*/ /*2*/ /*3*/
/*0*/ {0, 3, INF, 5},
/*1*/ {3, 0, 4, INF},
/*2*/ {INF, 4, 0, 2},
/*3*/ {5, INF, 2, 0}}
#include <iostream>
#include <vector>
#include <algorithm>
#include "stdio.h"
using namespace std;
#define INF 99
// /*A*//*B*//*C*//*D*//*E*//*F*//*G*/
//int global_map[][6] = // {
// /*A*/ { 0, 12, INF, INF, INF, 16, 14},
// /*B*/ { 12, 0, 10, INF, INF, 7, INF},
// /*C*/ { INF, 10, 0, 3, 5, 6, INF},
// /*D*/ { INF, INF, 3, 0, 4, INF, INF},
// /*E*/ { INF, INF, 5, 4, 0, 2, 8},
// /*F*/ { 16, 7, 6, INF, 2, 0, 9},
// /*G*/ { 14, INF, INF, INF, 8, 9, 0}};
/*int N = sizeof(global_map) / sizeof(global_map[0]);
int M = sizeof(global_map[0]) / sizeof(global_map[0][0]);
vector<vector<int>> vec_map(N, vector<int>(M));
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
vec_map[i][j] = global_map[i][j];
}
}
for(auto i : vec_map)
{
for(auto j : i)
{
cout<< j << " ";
}
cout << endl;
}*/
void Dij(int& start, int& end, vector<vector<int>>& map, int* pre)
{
int N = map.size();
cout << "N = " <<N<<endl;
int dist[N]; // dist[i]最终会保存起点到i节点的最短距离
std::fill(dist, dist + N, INF); // 先将每个值初始化为很大的数
bool visit[N];
std::fill(visit, visit + N, false); // visit起到剪枝的作用
for(int i = 0; i < N; i++)
{
pre[i] = i; // 初始化
}
dist[start] = 0; // 起点距离为0
for(int i = 0; i < N; i++)
{
int u = -1;
int min = INF;
for(int j = 0; j < N; j++)
{
if(!visit[j] && dist[j] < min) // 已经为父节点的节点就不会再参与计算,找出剩余节点的最短距离
{
u = j; // u 为父节点
min = dist[j];
}
}
if(u == -1 || u == end) // 是否找到终点
{
cout << "mh find u == end "<<endl;
break;
}
visit[u] = true; // 剪枝
for(int v = 0; v < N; v++)
{
if(!visit[v] && map[u][v] != INF)
{
if(dist[u] + map[u][v] < dist[v]) // 是否松弛
{
dist[v] = dist[u] + map[u][v]; //重新更新节点距离
pre[v] = u; // 重新更新,表示节点 v 的父节点为 u
cout << "pre["<< v <<"] =" << u << " " << "u_dist["<< u<<"] = " << dist[u]<< " " ;
cout <<"v_dist["<< v <<"] = "<< dist[v]<<endl;
}
}
}
//cout<<"test.....3"<<endl;
}
int t = end;
cout<<"path = ";
vector<int> path; // 保存起点到终点的路径点
while(pre[t] != t) // 从终点往起点遍历
{
path.push_back(t);
t = pre[t];
}
// 下面为打印的结果,不懂的地方可以通过此数据分析
//pre[0] =1 u_dist[1] = 0 v_dist[0] = 3
//pre[2] =1 u_dist[1] = 0 v_dist[2] = 4
//pre[3] =0 u_dist[0] = 3 v_dist[3] = 8
//pre[3] =2 u_dist[2] = 4 v_dist[3] = 6 //注意通过松弛后,pre[3]的父节点:由 0 变为 2
//dist[3]最短距离:由 8 变为 6
path.push_back(start);
reverse(path.begin(), path.end());
for(auto p : path)
{
cout<< p <<" "; // path = 1 2 3
}
cout<<endl;
cout<< "Total min length = " << dist[end] << endl; // Total min length = 6
}
int main()
{
vector<vector<int>> global_map = {
{0, 3, INF, 5, INF, INF},
{3, 0, 4, INF, INF, INF},
{INF, 4, 0, 2, INF, INF},
{5, INF, 2, 0, INF, INF},
{INF, INF, INF, INF, INF, INF},
{INF, INF, INF, INF, INF, INF }
};
int a[6];
int start = 1;
int end = 3;
Dij(start, end, global_map, a);
return 0;
}
版权声明:本文为qq_36458461原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。