1、问题描述
™
给定一个有向带权图
G=(V
,
E)
,其中每条边的权是一个非负实数。另外,给定
V
中的一个顶点,称为源点。计算从源点到所有其它各个顶点的最短路径长度,这里的路径长度是指路径上经过的所有边上的权值之和。
2、算法设计
1)算法思想
2、算法设计
1)算法思想
按各个顶点与源点之间路径长度的
递增
次序,生成源点到各个顶点的最短路径的方法,即先求出长度最短的一条路径,再参照它求出长度次短的一条路径,依此类推,直到从源点到其它各个顶点的最短路径全部求出为止。
2)算法步骤
2)算法步骤
步骤
1
:设计合适的数据结构。带权邻接矩阵
C
,即如果
< u, x >E
,令
C[u][x]=<u, x >
的权值,否则,
C[u][x]=
无穷;采用数组
dist
来记录从源点到其它顶点的最短路径长度;采用数组
p
来记录最短路径;
步骤
2
:初始化。令集合
S={u}
,对于集合
V-S
中的所有顶点
x
,设置
dist[x]=C[u][x]
;如果顶点
i
与源点相邻,设置
p[
i
]=u
,否则
p[
i
]=-1
;
步骤
3
:在集合
V-S
中依照贪心策略来寻找使得
dist[x]
具有最小值的顶点
t
,
t
就是集合
V-S
中距离源点
u
最近的顶点。
步骤
4
:将顶点
t
加入集合
S
中,同时更新集合
V-S
;
步骤
5
:如果集合
V-S
为空,算法结束;否则,转步骤
6
;
步骤
6
:对集合
V-S
中的所有与顶点
t
相邻的顶点
x
,如果
dist[x]>dist[t]+C[t][x]
,则
dist[x]=dist[t]+C[t][x]
并设置
p[x]=t
。转步骤
3
。
3、代码
3、代码
#include<iostream>
#include<vector>
using namespace std;
const int Maxval=0x7FFFFFFF;//无穷大
const int Node=5;//图的节点个数
int C[Node][Node]={//设置图的节点间的权值,本身到本身为0
{0,8,32,Maxval,Maxval},
{12,0,16,17,Maxval},
{Maxval,29,0,Maxval,13},
{Maxval,21,Maxval,0,7},
{Maxval,Maxval,27,19,0}
};
int dist[Node-1]={Maxval};//记录从原节点到其他节点的最短路径长度,初始值设为无穷大
int p[Node]={-2};//记录最短路径
vector<int> S,VmS;
void Init(int V[])
{
S.push_back(V[0]);//初始化集合S和V-S,S集合中只包含起始节点,其余节点在V-S中
for(int i=1;i<Node;++i)
{
VmS.push_back(V[i]);
}
for(auto it1=VmS.begin();it1!=VmS.end();++it1)//容器中存储的数据是节点的编号
{
dist[(*it1)]=C[0][*it1];
if(dist[(*it1)]!=Maxval)
{
p[(*it1)]=0;
}
else
p[(*it1)]=-1;
}
}
void PrintS()//打印选取节点的顺序
{
cout<<"节点加入S的顺序:";
for(auto it=S.begin();it!=S.end();++it)
cout<<*it<<" ";
cout<<endl;
}
void PrintP(int p[])//打印最短路径
{
for(auto it=S.begin();it!=S.end();++it)
{
cout<<*it<<"的最短路径为:";
for(int i=1;i<=(*it);++i)
{
if(i==1)
cout<<p[i]<<"->";
else if(p[i]!=-1&&p[i]!=p[i-1])
cout<<p[i]<<"->";
}
cout<<*it<<endl;
}
}
void dijkstra(vector<int> &,vector<int> &)
{
int mindist=Maxval,t;
for(auto it=VmS.begin();it!=VmS.end();++it)
{
if(dist[(*it)]<mindist)//找出距离最小的点
{
mindist=dist[(*it)];
t=(*it);
}
}
auto it=VmS.begin();//删除V-S集合中的节点
while(it!=VmS.end())
{
if((*it)==t)
{
VmS.erase(it);
break;
}
else ++it;
}
S.push_back(t);//将该节点加入到S集合中
if(!VmS.empty())
{
for(auto it=VmS.begin();it!=VmS.end();++it)
{
if(C[t][*it]!=Maxval)
{
if(dist[(*it)]>dist[t]+C[t][(*it)])
{
dist[(*it)]=dist[t]+C[t][(*it)];
p[*it]=t;
}
}
}
dijkstra(S,VmS);
}
else
{
PrintS();
}
}
int main()
{
int V[Node]={-1};//存储节点编号
for(int i=0;i<Node;++i)//节点编号初始化
{
V[i]=i;
}
Init(V);
dijkstra(S,VmS);
PrintP(p);
system("pause");
return 0;
}