算法基础—Dijkstra算法
brycezou@163.com
1、最优子结构
如果 d(i,j)={Vi,⋯,Vm,⋯,Vn,⋯,Vj} 是从顶点 i 到
用反证法进行证明:假设 d(i,j) 是从顶点 i 到
由最短路径的最优子结构性质可知,如果存在一条从 i 到
dist[u]=min{dist[u], dist[k]+graph[k][u]}
其中, dist[u] 用来记录从源点 V0 到顶点 Vu 的最短路径的长度。
2、Dijkstra算法
Dijkstra算法的基本思想:设 G=(V,E) 是一个带权有向图,把图中的顶点集合 V 分成两组,第一组为已求出最短路径的顶点集合,用
算法步骤:
a)初始时,集合
b)从 U 中选取一个与
c)以
d)重复步骤 b 和 c 直到所有顶点都包含在 S <script type="math/tex" id="MathJax-Element-148">S</script> 中。
3、算法代码示例
本算法代码,旨在清晰地展示算法细节,而未进行任何优化,请多多包涵。
#include <iostream>
#include <stack>
using namespace std;
#define MAX_VERTEX 5
#define MAX_DIST 65535
void show_path(int prev_node[],int v0,int u) //打印最短路径上的各个顶点
{
stack<int> stk;
while(u != v0)
{
stk.push(u);
u = prev_node[u]; //取前驱节点
}
stk.push(u);
while(!stk.empty())
{
cout<<stk.top()<<" ";
stk.pop();
}
}
int graph[MAX_VERTEX][MAX_VERTEX];
int dist[MAX_VERTEX];
int prev_node[MAX_VERTEX];
bool visited[MAX_VERTEX];
int main(int argc, char *argv[])
{
cout << "Hello Dijkstra!" << endl;
for(int i = 0; i < MAX_VERTEX; i++)
{
for(int j = 0; j <= i; j++)
{
if(i==j)
graph[i][j] = 0;
else
graph[i][j] = graph[j][i] = MAX_DIST;
}
}
graph[0][1] = 100;
graph[0][2] = 30;
graph[0][4] = 10;
graph[2][1] = 60;
graph[2][3] = 60;
graph[3][1] = 10;
graph[4][3] = 50;
int v0 = 0;
for(int i = 0; i < MAX_VERTEX; i++)
{
dist[i] = MAX_DIST;
prev_node[i] = -1;
visited[i] = false;
if(graph[v0][i] < MAX_DIST && i != v0)
{
dist[i] = graph[v0][i];
prev_node[i] = v0;
}
}
dist[v0] = 0;
prev_node[v0] = v0;
visited[v0] = true;
for(int k = 1; k < MAX_VERTEX; k++) //循环扩展N-1次
{
int min_dist = MAX_DIST;
int u;
for(int i = 0; i < MAX_VERTEX; i++) //寻找未被访问的权值最小的顶点
{
if((!visited[i]) && (dist[i] < min_dist))
{
min_dist = dist[i];
u = i;
}
}
visited[u] = true;
for(int i = 0; i < MAX_VERTEX; i++) //更新dist数组的值和路径的值
{
if((!visited[i]) && (graph[u][i] < MAX_DIST) && (dist[u]+graph[u][i] < dist[i]))
{
dist[i] = dist[u]+graph[u][i];
prev_node[i] = u; //记录前驱顶点
}
}
}
for(int i = 0; i < MAX_VERTEX; i++)
{
if(i != v0)
{
show_path(prev_node, v0, i);
cout<<dist[i]<<endl;
}
}
cout<<""<<endl;
return 0;
}