Dijkstra
本篇文章属于个人笔记,不适合详细了解和解读此算法 ,不过代码,代码已详细注释可以学习参考。
简介
实现单源点最短路
- 此算法可以得出单源点到达其他节点的最短路径和权值
思路
-
前置: 距离数组,前置数组
-
初始化
-
图全部初始化为无穷大
-
输入 顶点 边
-
输入源点
-
-
寻找最短路
-
将源点添加到S数组【视为当前最优】
-
将源点的距离设置为 0
-
开始寻找dist(距离)中最小的,并得到距离最小的节点
-
将找到的添加到S数组中
-
从 当前得到的最小节点开始拓展最小节点可以到达的节点 和当前源节点能到达的节点 进行距离比较
- 如果从最小节点到达最优
- 到达的节点 dist距离更新,前置更改为 最小节点
- 其他情况保持原状
- 如果从最小节点到达最优
-
返回 三步骤,直到全部 节点标记到S数组
-
代码实现[详细注解]
#include <iostream>
#include <cstring>
using namespace std;
const int N = 999999;// 无限大
typedef struct{
int vex[100]; // 顶点
int edge[100][100]; //边
int vexnum; // 顶点总数
int edgenum; // 边总数
}maps;
/*
5
8
1 2 3 4 5
1 2 2
1 3 5
2 3 2
2 4 6
3 4 7
3 5 1
4 3 2
4 5 4
1
*/
int dist[100]; // 距离
int pervious[100]; // 上一个
bool flag[100]; // 是否是s集合
int find_vex(maps g,int u){
for (int i = 1; i <= g.vexnum; i++)
{
if(g.vex[i] == u) return i;
}
return -1;
}
void Create_map(maps &g){
cout << "请输入节点大小:";
cin >> g.vexnum;
cout << "请输入边的大小:";
cin >> g.edgenum;
/* 初始化图 */
for (int i = 1; i <= g.vexnum; i++)
{
for(int j = 1; j <= g.vexnum;j++){
g.edge[i][j] = N;
}
}
cout << "图初始化完成" << endl;
/* 初始化结束 */
/* 输入顶点 */
int u,v,w; // 源点,终点,权值
cout << "请输入顶点:";
for (int i = 1; i <= g.vexnum; i++)
{
cin >> g.vex[i];
}
/* 输入顶点结束 */
cout <<"顶点输入完毕" << endl;
/* 输入边 */
for (int i = 1; i <= g.edgenum; i++)
{
cin >> u >> v >> w;
u = find_vex(g,u);
v = find_vex(g,v);
if(u!=-1 && v!=-1){ // 如果找到了
g.edge[u][v] = w;
}else{
cout << "XXXXX.XXXXXX输入错误!!" << endl;
i--;
}
}
/* 输入边结束 */
cout << "=-输入完毕-= 初始化完成";
}
void dijkstra(maps g,int u ){
/* 最短路 */
/*Step1 初始化 dist and pervious */
for (int i = 1; i <= g.vexnum; i++){
if(g.edge[u][i]!=N){
/* 如果可到达 */
dist[i] = g.edge[u][i];
pervious[i] = u;
}else{
/* 如果不可到达 */
dist[i] = N;
pervious[i] = -1;
}
}
/*Step2 初始化起点 */
dist[u] = 0;
flag[u] = true;
/*Step3 遍历*/
for (int i = 1; i <= g.vexnum; i++)
{
int temp_min = N; // 最小距离
int temp_min_node = u; // 最小节点
/* 寻找最小节点 */
for (int j = 1; j <= g.vexnum; j++){
if(!flag[j] && dist[j] < temp_min){
temp_min = dist[j];
temp_min_node = j;
}
}
/* 寻找最小节点结束 */
if (temp_min_node == u) return; // 没找到
flag[temp_min_node] = true; // 加入优先集合
/* 遍历刚加入优先集合可到达的节点和原先的节点进行距离比较 */
for (int j = 1; j <= g.vexnum; j++){
if(!flag[j] && g.edge[temp_min_node][j]!=N){
if(dist[j] > (dist[temp_min_node] + g.edge[temp_min_node][j])){
dist[j] = dist[temp_min_node]+g.edge[temp_min_node][j];
pervious[j] = temp_min_node;
}
}
}
}
}
int main(){
maps G;
memset(flag,false,sizeof(flag));
memset(dist,-1,sizeof(dist)); // 初始化距离
memset(pervious,-1,sizeof(pervious));
Create_map(G);
cout << "请输入开始的源点:";
int u;
cin >> u;
u = find_vex(G,u);
dijkstra(G,u);
cout <<"Start:" << u << endl;
for (int i = 1; i <= G.vexnum; i++)
{
int v = find_vex(G,i);
cout << u << " to " << i << " "<<dist[v] << endl;
}
}