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;
}