数据结构(最短路径)

最短路径算法

  在网图和非网图中,最短路径的含义是不一样的:数组

  • 网图是两顶点通过的边上的权之和最小的路径
  • 非网图是两顶点之间通过的边数最少的路径
  • 把路径起始的第一个顶点称为源点。最后一个顶点称为终点

  主要的方法有两种:spa

  • 迪杰斯特拉算法:求顶点到全部顶点的最短路径。O(n²)
  • 弗洛伊德算法:求全部顶点到全部顶点的最短路径。O(n³)

迪杰斯特拉算法3d

算法思路:code

  一步步求与每一个顶点的最短路径,过程当中都是基于已经求出的最段路径的基础上,求得更远顶点的最段路泾,最终获得想要顶点的最段路径(其实与普利姆算法是很是类似的)blog

方法:递归

  • 用3个数组:final数组,ShortPathTable数组,Patharc数组
  • final数组:标记顶点是否已求出最短路径(0/1)
  • ShortPathTable数组:存储当前进度源点到各顶点的最短距离
  • Patharc数组:存储当前对应位置当前ShortPathTable数组距离路径的前驱

 1 #define MAXVEX 9//宏定义图的最大定点数
 2 #define INFINITY 65535//路不通时的默认值
 3 
 4 typedef int Patharc[MAXVEX]//用于存储最段路经下标的数据
 5 typedef int ShortPathTable[MaxVEX]//用于存储到各点的最短路径的权值和
 6 
 7 //G:图结构:are,矩阵二维数组;numVertexes,图中顶点数
 8 //A:用于传入源点
 9 //P就是Patharc数组,用于存储源点到下标位置对应顶点为终点的最短路径的倒数第二个顶点的下标(最段路经终点的前驱)
10 //D就是ShortPathTable数组,用于存储各源点A到其余各点的最短路径权之和
11 void ShortestPath_Dijkstar(MGraph G,int A,patharc *P,ShortPathTable *D){
12     int v,w,k,min;
13     int final[MAXVEX];//标记数组:用于标志是否已经找到源点到对定位置的最段路经【0表示未找到,1表示已经找到】
14     
15     //初始化数据
16     for(v=0;v<G.numVertexes;v++){
17         final[v]=0;//所有顶点初始化为未找到最段路泾
18         (*D)[v]=G.are[A][v];//由于寻找A下标顶点到各顶点的最短路径,因此初始化时就是为矩阵中第v行的数据(这行数据就是这个顶点到各顶点的权)
19         (*P)[v]=0;//初始化路径数组为0
20     }
21     (*D)[A]=0;//源点到源点的路径权为0
22     final[A]=1;//源点到源点的路径已经找到
23 
24     //开始循环,找源点到其余[G.numVertexes-1]个顶点的最短路径
25     for(v=1;v<G.numVertexes;v++){//【循环1】:循环一次找到一个源点到其余点【X】的最短路径
26         min=INFINITY;
27         for(w=0;w<G.numVertexes;w++){
28             if(!final[w] && (*D)[w]<min){//在未找到最短路径的顶点中找当前距离源点权最近的那个顶点,这个顶点就是【循环1】本次循环所找到的【X】
29                 k=w;//记录此次找到最短路径的终点下标
30                 min=(*D)[w];//记录此次找到点的最短路径的权(这里的权就是这条路径的权之和)
31             }
32         }
33         final[k]=1;//标记源点到该顶点为终点的最短路径已经找
34 
35         //修正当点进度源点到各点的最短距离;由于为源点多加了一条边,就为源点到各点添加了若干条路,这些路会有刷新源点到其余点的最短距离
36         for(w=0;w<G.numVertexes;w++){
37             //未找最短路径到的顶点【Y】中;从源点到【X】再到【Y】的距离小于原先距离,就刷新了原先到【Y】的距离
38             if(!final[w] && (min+G.arc[k][w] < (*D)[w])){
39                 (*D)[w]=min+G.arc[k][w];//刷新该距离
40                 (*P)[w]=k;//记录刷新到w顶点的最短距离的顶点,也是这条当前最短距离路径的前驱
41             }
42         }
43     }
44 }

弗洛伊德算法class

  求是是全部顶点到全部顶点的距离;O(n³)test

算法思路:基础

  判断两顶点之间依次通过任意中间点是否会减短原先路径,能够的话就在路径上添加这个中间点,判断过所有中间点后就获得了全部能减短路径的中间点,那么两点和这些有效的中间点之间的路径就都成了短路径;

查找最短路径:

  查找时则是在Pathmatirx数组中查看是否存在中间点(-1表明没有中间点);如有中间点则递归查找源点到中间点的最短距离中间点到终点的最短路径,没有中间点就表示源点直接到终点就是最短路径,打印这条路径,返回便可;

方法:

  • 定义中间点
  • 刚开始定义中间点位0,那么就判断所有顶点中任意两顶点,源点经过0再走向终点的距离是够小于源点直接走向终点的距离
  • 小于的话,那么就在Pathmatirx数组中Pathmatirx【源点下标】【终点下标】位置修改成中间点下标的位置;不然不作处理
  • 循环①,③,③步骤,让中间点从0~【G.numVertexes-1】循环过去便可

 1 #define MAXVEX 9//宏定义图的最大定点数
 2 #define INFINITY 65535//路不通时的默认值
 3 
 4 typedef int Pathmatirx[MAXVEX][MAXVEX]//用于存储最段路经下标的数据
 5 typedef int ShortPathTable[MaxVEX][MaxVEX]//用于存储到各点的最短路径的权值和
 6 
 7 void ShortesPath_Floyd(MGraph G,Pathmatirx *D,ShortPathTable *D){
 8     int v,w,k;
 9     //初始化D和P
10     for(v=0;V<G.numVertexes;v++){
11         for(w=0;w<G.numVertexes;w++){
12             (*D)[v][w]=G.matirx[v][w];
13             (*P)[v][w]=w;
14         }
15     }
16 
17     //弗洛伊德算法
18     for(k=0;k<G.numVertexes;k++){
19         for(v=0;v<G.numVertexes;v++){
20             for(w=0;w<G.numVertexes;w++){
21                 if( (*D)[v][w] > (*D)[v][w] + (*D)[k][w] ){
22                     (*D)[v][w]=(*D)[v][w]+(*D)[k][w];
23                     (*P)[v][w]=(*P)[v][k];
24                 }
25             }
26         }
27     }
28 }
29 
30 void printPath(MGraph G,int u,int v,int Pathmatirx[][MAXVEX]){
31     int mid;
32     if(Pathmatirx[u][v]==-1)
33         printf("<%c,%c>  ",G.lin[u],G.lin[v]);
34     else{
35         mid= Pathmatirx[u][v];
36         printPath(G,u,mid,Pathmatirx);
37         printPath(G,mid,v,Pathmatirx);
38     }
39 }