迪杰斯特拉(Dijkstra)
迪杰斯特拉提出了一个按路径长度递增的次序产生最短路径的算法,其实这也是一个贪心的过程,,,,
算法步骤:
首先要明白三个数组:
bool s[MAXN]; //记录从源点v0到终点vi是否已被确认最短路径长度
int path[MAXN]; //记录从源点v0到终点vi的当前直接前驱顶点序号
int D[MAXN]; //记录从源点v0到终点v1的当前最短路径
所以说,s[i]原来判断,path[i]原来查找路径,D[i]中存最短路。
1、初始时,S 只包含源点,即 S={v},v 的距离为 0。U 包含除 v 外的其他顶点,即:U={其余顶点},若 v 与 U 中顶点 u 有边,则 正常有权值,若 u 不是 v 的邻接点,则 权值为 ∞。
2、从 U 中选取一个距离 v 最小的顶点 k,把 k加入 S 中(该选定的距离就是 v 到 k 的最短路径长度)。
3、以 k 为新考虑的中间点,修改 U 中各顶点的距离;若从源点v 到顶点 u 的距离(经过顶点 k)比原来距离(不经过顶点k)短,则修改顶点 u 的距离值,修改后的距离值的顶点 k 的距离加上边上的权。
4、重复步骤 2 和 3 直到所有顶点都包含在 S 中。
样例输出:
代码块:
//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<math.h>
using namespace std ;
typedef long long ll;
#define MAXN 105
#define INF 0x3f3f3f3f
#define MALL (Bithrnode *)malloc(sizeof(Bithrnode));
bool s[MAXN]; //记录从源点v0到终点vi是否已被确认最短路径长度
int path[MAXN]; //记录从源点v0到终点vi的当前直接前驱顶点序号
int D[MAXN]; //记录从源点v0到终点v1的当前最短路径
typedef struct
{
int vexs[MAXN]; //顶点表
int arcs[MAXN][MAXN]; //邻接矩阵
int vexnum, arcnum; //图的当前点数和边数
} AMGraph;
void init(AMGraph &G)
{
cout << "请输入顶点数vex和边数arc:" << '\n';
cin >> G.vexnum >> G.arcnum; //输入点数和边数
cout << "请依次输入各个顶点的代号(可以用int, char和string)" << '\n';
for(int i=0; i<G.vexnum; ++i)
cin >> G.vexs[i];
for(int i=0; i<G.vexnum; ++i) //初始化矩阵,边的权值为无穷大INF
for(int j=0; j<G.vexnum; ++j)
G.arcs[i][j] = INF;
cout << "请输入arc条边与边的关系" << '\n';
for(int k=0; k<G.arcnum; ++k)
{
int u, v, len, i, j;
cin >> u >> v >> len;
for(int c=0; c<G.vexnum; ++c) //查找u、v在顶点集中的位置
{
if(G.vexs[c] == u)
i = c;
if(G.vexs[c] == v)
j = c;
}
G.arcs[i][j] = len; //有向图
// G.arcs[j][i] = len;
}
}
void Dijkstra(AMGraph G, int v0)
{
//用Dijkstra算法求有向图G的v0顶点到其余顶点的最短路径
int n = G.vexnum;
for(int i=0; i<n; ++i) //初始化n个顶点
{
s[i] = false;
D[i] = G.arcs[v0][i]; //将v0到各个终点的最短路径长度初始化为其弧的权值
if(D[i] < INF) //如果v0和i之间有弧,则将i的前驱置为v0
path[i] = v0;
else //如果v0和i之间无弧,则置为-1;
path[i] = -1;
}
s[v0] = true; //将v0加入s,
D[v0] = 0;
for(int i=1; i<n; ++i) //检索其余的n-1个顶点
{
int minn = INF, x;
for(int j=0; j<n; ++j)
{
if(!s[j] && D[j] < minn)
{
x = j;
minn = D[j];
}
}
s[x] = true;
for(int j=0; j<n; ++j)
{
if(!s[j] && D[x] + G.arcs[x][j] < D[j])
{
D[j] = D[x] + G.arcs[x][j];
path[j] = x;
}
}
}
}
void print(int n)
{
for(int i=1; i<n; ++i)
if(D[i] < INF)
printf("v0->v%d: %d\n", i, D[i]);
else
printf("v0->v%d: 不可通行\n", i);
}
int main()
{
AMGraph G;
init(G);
Dijkstra(G, 0);
print(G.vexnum);
}
Dijkstra:
void Dijkstra(AMGraph G, int v0)
{
//用Dijkstra算法求有向图G的v0顶点到其余顶点的最短路径
int n = G.vexnum;
for(int i=0; i<n; ++i) //初始化n个顶点
{
s[i] = false;
D[i] = G.arcs[v0][i]; //将v0到各个终点的最短路径长度初始化为其弧的权值
if(D[i] < INF) //如果v0和i之间有弧,则将i的前驱置为v0
path[i] = v0;
else //如果v0和i之间无弧,则置为-1;
path[i] = -1;
}
s[v0] = true; //将v0加入s,
D[v0] = 0;
for(int i=1; i<n; ++i) //检索其余的n-1个顶点
{
int minn = INF, x;
for(int j=0; j<n; ++j)
{
if(!s[j] && D[j] < minn) //选择一条当前的最短路径,终点为x
{
x = j;
minn = D[j];
}
}
s[x] = true; //将x加入S中
for(int j=0; j<n; ++j)
{
if(!s[j] && D[x] + G.arcs[x][j] < D[j])
{
D[j] = D[x] + G.arcs[x][j]; //更新D[j]
path[j] = x; //更新j的前驱为x
}
}
}
}