大话数据结构——图论再讨论(五)~最短路径~2020.9.7

最短路径

最短路径分为迪杰斯特拉与弗洛伊德算法,且听我娓娓道来。
单源最短路径——迪杰斯特拉

#include <iostream>
#include <cstring>
using namespace std;
const int MAXVEX = 105;
const int INFINITY = 65535;
struct MGraph{
 int arc[MAXVEX][MAXVEX];
 int vexes[MAXVEX];
 int numVertexes,numEdges;
};
void CreateMGraph(MGraph *G){
 cout<<"输入顶点个数与边的个数";
 cin>>G->numVertexes>>G->numEdges;
 cout<<"输入顶点信息:";
 for(int i=0;i<G->numVertexes;i++){
  cin>>G->vexes[i];
 }
 for(int i=0;i<G->numVertexes;i++){
  for(int j=0;j<G->numVertexes;j++){
   if(i == j) G->arc[i][j] = 0;
   else  G->arc[i][j] = INFINITY;
  }
 }
 cout<<"输入边的信息:";
 for(int i=0;i<G->numEdges;i++){
  int j,k,l;
  cin>>j>>k>>l;
  G->arc[j][k] = l;
  G->arc[k][j] = G->arc[j][k];
 }
}
int D[MAXVEX] = {0};//用于存储从v0到各个顶点的最短路径 
int P[MAXVEX] = {0};//用于存储自v0前往各个顶点的路径
bool final[MAXVEX];  
void Dijkstra(MGraph *G,int v0){
 memset(final,false,sizeof(final));
 //下方进行初始化操作 
 for(int i=0;i<G->numVertexes;i++){
  D[i] = G->arc[v0][i];//D数组记录的是从v0到v的距离 
  P[i] = 0;//P记录最短路径 
 }
 final[v0] = true;//表示v0顶点的最短路径已经找到 (即它本身) 
 for(int v=0;v<G->numVertexes;v++){//对所有顶点进行遍历 
  int MIN = INFINITY,k;//k记录当前最短路径(v0,v)中v的下标 
  for(int w=0;w<G->numVertexes;w++){//寻找自v0到某顶点的最短路径 
   if(!final[w]&&D[w]<MIN){//记住:D数组记录的是从v0到
   //数组下标顶点的最短路径。
    MIN = D[w];
    k = w;
   }
  }
  final[k] = true;
  //下面通过得到的MIN值松弛D数组
  //MIN值的意义是自v0到k的距离,这个距离已经是最短的了 
  for(int w=0;w<G->numVertexes;w++){
   if(!final[w]&&MIN+G->arc[k][w]<D[w]){
    D[w] = MIN + G->arc[k][w];
    P[w] = k;
   }
  } /*看似最外层的循环变量v在整个内部循环中都没有起到
  作用,但每经过一次循环,D数组中的数值都得到了松弛。*/
 }
}
int main()
{
 MGraph G;
 CreateMGraph(&G);
 Dijkstra(&G,0);
 for(int i=0;i<G.numVertexes;i++){
  cout<<D[i]<<' ';
 }
 return 0;
}

思想是通过一个外层循环,每次找到当前最短路径,并用这个最短路径松弛其他顶点,得到整张图的单源最短路径,时间复杂度为O(n ^ 2)。
多元最短路径——弗洛伊德算法
弗洛伊德算法使用三重循环,非常巧妙的求出了邻接矩阵每一个顶点到另外所有顶点的最短路径,当然时间复杂度为O(n ^ 3),参与竞赛的朋友请在数据小于200时(200左右也勉强可以)使用。

#include <iostream>
#include <cstring>
using namespace std;
const int MAXVEX = 105;
const int INFINITY = 65535;
struct MGraph{
 int arc[MAXVEX][MAXVEX];
 int vexes[MAXVEX];
 int numVertexes,numEdges;
};
void CreateMGraph(MGraph *G){
 cout<<"输入顶点个数与边的个数";
 cin>>G->numVertexes>>G->numEdges;
 cout<<"输入顶点信息:";
 for(int i=0;i<G->numVertexes;i++){
  cin>>G->vexes[i];
 }
 for(int i=0;i<G->numVertexes;i++){
  for(int j=0;j<G->numVertexes;j++){
   if(i == j) G->arc[i][j] = 0;
   else  G->arc[i][j] = INFINITY;
  }
 }
 cout<<"输入边的信息:";
 for(int i=0;i<G->numEdges;i++){
  int j,k,l;
  cin>>j>>k>>l;
  G->arc[j][k] = l;
  G->arc[k][j] = G->arc[j][k];
 }
}
int D[MAXVEX][MAXVEX] = {0};
int P[MAXVEX][MAXVEX] = {0};
void Floyd(MGraph *G){
//两个循环完成初始化操作
 for(int i=0;i<G->numVertexes;i++){
  for(int j=0;j<G->numVertexes;j++){
   D[i][j] = G->arc[i][j];
   P[i][j] = j;
  }
 }
 //Floyd算法太完美了,没有什么好说明的,一切尽在代码中
 for(int k=0;k<G->numVertexes;k++){//最外层循环用于寻找中继结点 
  for(int v=0;v<G->numVertexes;v++){
   for(int w=0;w<G->numVertexes;w++){
    if(D[v][w]>D[v][k]+D[k][w]){
     D[v][w] = D[v][k]+D[k][w];
     P[v][w] = P[v][k];
    }
   }
  }
 }//时间复杂度O(n ^ 3),不断松弛D数组以求得多元最短路径 
}
//用于打印邻接矩阵最短路径的函数ShowPath()
void ShowPath(MGraph *G)
{
 for(int v=0;v<G->numVertexes;v++){
  for(int w=v+1;w<G->numVertexes;w++){//w的循环值为v+1,没有必要重复打印路径 
   cout<<"("<<v<<","<<w<<")-weight:"<<D[v][w];
   cout<<endl<<"Path:"<<v<<"->";
   int k = P[v][w];
   while(k!=w){
    cout<<k;
    k = P[k][w];
    cout<<"->";
   }
   cout<<w;
   cout<<endl;
  }
  cout<<endl;
 }
}
int main()
{
 MGraph G;
 CreateMGraph(&G);
 Floyd(&G);
 ShowPath(&G);
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值