核心算法思路:
在迪杰斯特拉算法每次确定路径后优化路径时,当更新distance(记录最短路径长度的数组)值时也将信息写入散列,最后散列记录下来的路径即是最短路径的行进路线。
核心算法伪代码:
const int INF=100000 ;
void Widget::dijkstra(初始点)
{
将path[]初始化为-1 //path是路径散列
将vis[]初始化为0 //vis[i]为0表示节点i未被访问
将distan[]初始化为INF //distan[i]是i点到初始点的距离
distan[begin]=0; //将起始点到自身的距离设为0
for(int i=0 ,开始遍历,遍历节点次)
{
int u = -1 , MIN = INF;//初始化u和MIN,u用于记录查找到MIN的位置(节点序号)
for(int j=0 ,开始遍历,遍历节点次)
{
if(节点j未被访问 && distan[j]储存的值小于MIN)
{
记录该位置并更新MIN
}
}
if(未找到新的MIN值,可说明剩余点不连通,退出算法)return ;
vis[u] = true; //记u被访问
for(int v=0 ,开始遍历,遍历节点次)//开始对路径进行优化
{
if( v点未被访问 && 图上u和v连通 && distan[u]+d[u][v]<distan[v])//最后一个判断条件的意思是如果我从新添加的节点走向v比distan[v]记录的更短,说明前者更优
{
更新distan[v]为distan[u]+d[u][v]
path[v]=u;//将v的上一路径点设置为u
}
}
}
return ;
}
核心算法C / C++源代码:
int dijkstra(int begin)
{
for(int i=0;i<n;i++)
{
path[i]=-1;
vis[i]=0;
distances[i]=INF;
}
//起始点到其自身的距离设为0
distances[begin]=0;
for(int i=0;i<n;i++)
{
int u=-1,MIN=INF;
for(int j=0;j<n;j++)
{
//从V-S中选择节点(V指全集,S指已经连通的节点)
if( !vis[j] && distances[j]<MIN )
{
u=j;
MIN=distances[j];
}
}
//没有找到新的MIN值
if(u==-1)
{
return 0;//非连通图
}
//记录u点已访问
vis[u]=1;
//优化路径
for(int v=0;v<n;v++)
{
if(!vis[v] && distances[u]+d[u][v]<distances[v] )
{
distances[v]=distances[u]+d[u][v];
//记录路径
path[v]=u;
}
}
}
return 1;
}
完整代码解释:
下面的代码段是完整代码,包括核心函数,路径输出函数,测试数据(5*5矩阵,标签为从0到4); 不想再手搓一个栈用C++写的,栈的作用是将path的数据拿出来(由于path记录的是最短路径走到某一结点时该路径上的上一节点,所以是逆序的,用栈将其正序排列),测试时,输入的内容是起始点和终点,中间空格或回车隔开。
完整代码中测试用的邻接矩阵:
label:
0 1 2 3 4Graph:
0 1 2 1 1
1 0 4 7 4
2 4 0 2 8
1 7 2 0 6
1 4 8 6 0
完整代码:
#include <iostream>
#include <stack>
using namespace std;
const int INF = 100000;//极大数
const int n=5;
int d[n][n];
int distances[n];
int path[n],vis[n];
void init();
int dijkstra(int begin);
void out_route(int end);
//path为散列,用于存放行进路线——上一个行进节点,vis用于标记某个节点是否被访问
int main()
{
int b,e;
scanf("%d%d",&b,&e);
init();
dijkstra(b);
printf("min distance = %d\n",distances[e]);
out_route(e);
return 0;
}
void init()
{
for(int i=0;i<n;i++)
d[i][i]=0;
d[0][1]=1; d[1][0]=1;
d[0][2]=2; d[2][0]=2;
d[0][3]=1; d[3][0]=1;
d[0][4]=1; d[4][0]=1;
d[1][2]=4; d[2][1]=4;
d[1][3]=7; d[3][1]=4;
d[1][4]=4; d[4][1]=7;
d[2][3]=2; d[3][2]=2;
d[2][4]=8; d[4][2]=8;
d[3][4]=6; d[4][3]=6;
}
/**
label:
0 1 2 3 4
Graph:
0 1 2 1 1
1 0 4 7 4
2 4 0 2 8
1 7 2 0 6
1 4 8 6 0
*/
//默认邻接矩阵为5*5
int dijkstra(int begin)
{
for(int i=0;i<n;i++)
{
path[i]=-1;
vis[i]=0;
distances[i]=INF;
}
//起始点到其自身的距离设为0
distances[begin]=0;
for(int i=0;i<n;i++)
{
int u=-1,MIN=INF;
for(int j=0;j<n;j++)
{
//从V-S中选择节点(V指全集,S指已经连通的节点)
if( !vis[j] && distances[j]<MIN )
{
u=j;
MIN=distances[j];
}
}
//没有找到新的MIN值
if(u==-1)
{
return 0;//非连通图
}
//记录u点已访问
vis[u]=1;
//优化路径
for(int v=0;v<n;v++)
{
if(!vis[v] && distances[u]+d[u][v]<distances[v] )
{
distances[v]=distances[u]+d[u][v];
//记录路径
path[v]=u;
}
}
}
return 1;
}
//连通时使用,用于显示路径
void out_route(int end)
{
stack<int> st;
st.push(end);
while(path[end]!=-1)
{
st.push(path[end]);
end=path[end];
}
printf("min route : ");
while(!st.empty())
{
printf("%d ",st.top());
st.pop();
}
}
运行结果: