1、综述
Dijkstra(迪杰斯特拉)算法是典型的最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。
2、Dijkstra 算法
3、代码
#include <iostream>
#include <queue>
using namespace std;
#define N 5 //点
#define M 10 //边
//边结点结构
struct Edge
{
int start;//有向图的起点
int end;//有向图的终点
int value;
};
//顶点属性
struct Vertex
{
int d;//与的源点的距离
int p;//在最短路径树中的父结点
};
Vertex V[N+1];//顶点集合
Edge E[M+1];//边集合
bool visited[N+1] ;//这里用bool表示边是否被加入到S中,如果为true,则表示已经加入S中
//初始化
void Initialize_Single_Source(int s)
{
int i;
for(i = 1; i <= N; i++)
{
V[i].d = 0x7fffffff;//初始距离为无穷大
V[i].p = -1;//初始前驱点为-1
visited[i] = false;
}
V[s].d = 0;
}
//对边uv松弛,w为边uv的权重
void Relax(int u, int v, int w)
{
if(V[u].d != 0x7fffffff && V[v].d > V[u].d + w)
{
V[v].d = V[u].d + w;
V[v].p = u;
}
}
//输出每个顶点的属性
void Print()
{
int i;
for(i = 1; i <= N; i++)
cout<<V[i].d<<' ';
cout<<endl;
for(i = 1; i <= N; i++)
cout<<V[i].p<<' ';
cout<<endl;
}
////Bellman_Ford算法
//bool Bellman_Ford(int s)
//{
// int i, j;
// //初始化
// Initialize_Single_Source(s);
// //对图的边进行|V|-1遍操作
// for (i = 1; i < N; i++)
// {
// cout<<"第"<<i<<"轮:"<<endl;
// //依次对每条边进行松弛操作
// for(j = 1; j <= M; j++)
// {
// Relax(E[j].start, E[j].end, E[j].value);
// }
// //输出每一轮松弛后的结果
// Print();
// }
// //对负权回路进行检查
// for(j = 1; j <= M; j++)
// {
// if(V[E[j].end].d > V[E[j].start].d + E[j].value)
// return false;
// }
// return true;
//}
//Dijkstra算法
void Dijkstra(int s)
{
//初始化
Initialize_Single_Source(s);
//使用for循环代替队列,因为知道需要遍历的次数为N
for(int j = 1 ; j <=N ; j++)
{
int d = 0x7fffffff;
int u;
//找出当前未加入S中的点中距离源点s最近的点
for(int i=1 ; i <= N ; i++)
{
if(visited[i] == false && V[i].d < d)
{
d = V[i].d;
u = i;
}
}
visited[u] = true;//把找出来的点放入S中
cout<<"第"<<j<<"轮:"<<endl;
for(int j = 1 ; j <= M ; j++)
{
if(E[j].start == u)
Relax(E[j].start,E[j].end,E[j].value);//对以当前点u为起点的边松弛
}
Print();
}
}
int main()
{
int i;
//输入边
int edge[11][3] ={{0,0,0},{1,2,10},{1,5,5},{2,3,1},{2,5,2},{3,4,4},{4,1,7},{4,3,6},{5,2,3},{5,3,9},{5,4,2}};
for(i = 1; i <= M; i++)
{
E[i].start = edge[i][0];
E[i].end = edge[i][1];
E[i].value = edge[i][2];
}
//Bellman_Ford算法
//Bellman_Ford(1);
Dijkstra(1);
return 0;
}