1.最短路径概念
2.Dijkstra狄克斯特拉算法
思路:
创建标号表flag, index为节点编号,flag[index]表征节点是否已经访问。创建矩阵path,path[index]的值为,起点from到顶点index的最短路径中到顶点index的上一个节点,-1表示起点到当前节点无路径。创建矩阵dist,dist[index]的值为,起点form到顶点index的最短路径。
设定起点为from。
(1)初始化,除flag[from]之外的值均为false,代表尚未探寻成功最短路径。初始化dist的值为起点直接到当前节点的路径长度。初始化path的所有值为from,若起点到该顶点无路径,设定为-1。
(2) 进行n-1次循环:
a.寻找最短路径顶点:遍历寻找dist中,值最小且尚未探寻成功最小路径的顶点并记录其标号index。
b.标记最短路径顶点:flag[index]为true.代表到该顶点的最小路径该已经探寻成功。
c.更新剩余顶点的最短距离矩阵dist和路径矩阵path:遍历比较以index为中继点到剩余顶点的距离,和当前记录的最小距离dist。若前者小,则更新最小距离,并将path的对应值更新为中继点标号index。
特点:
(1).Dijkstra 算法中的两重循环都是关于n的,所以时间复杂度为:O(n.^2)。由于需要辅助标记矩阵flag,空间复杂度为O(n).
(2).仅仅适用于正权值图
代码:
//狄克斯特拉算法求最短路径
// adjMatrix--邻接矩阵
// n--顶点总数
// from--起始节点数
//path[index]的值为,起点from到顶点index的最短路径中到顶点index的上一个节点,-1表示起点到当前节点无路径
//dist[index]的值为,起点form到顶点index的最短路径
void dijkstra(int** adjMatrix,int n,int from,int* path,int* dist){
bool* flag=new bool[n];//顶点是否已经探寻
//initialization
for(int i=0;i<n;i++){
dist[i]=adjMatrix[from][i];
flag[i]=false;
if(i!=from&&dist[i]<MAX)
path[i]=from;
else
path[i]=-1;//代表无路径
}
dist[from]=0;
flag[from]=true;
int minDist,minIndex;
for(int k=1;k<n;k++){//主循环,还有n-1个顶点需要探寻路径
//寻找dist当前最短路径并记录标号
minDist=MAX;
minIndex=-1;
for(int i=0;i<n;i++)
if(!flag[i]&&dist[i]<minDist){
minDist=dist[i];
minIndex=i;
}
flag[minIndex]=true;//代表顶点minIndex的最短路径已经探寻成功
//以顶点minIndex为中继点,探寻到其余为探寻顶点的最短路径并更新dist和path
for(int i=0;i<n;i++)
if(!flag[i]&&(minDist+adjMatrix[minIndex][i])<dist[i]){
dist[i]=minDist+adjMatrix[minIndex][i];
path[i]=minIndex;
}
}
}
3.Floyd弗洛伊德算法和顶点间的最短路径
思路
(1)初始化距离矩阵dist和路径矩阵path
(2)循环0:k,对于每一个路径点[i][j](排除对角线点,自己以自己为中继的点)
a.dist[i][j]=min{ dist[i][j], dist[i][k]+dist[k][j]},即每次保证当添加k为中继点时,取路径最短的。
b.若更新成功,则path[i][j]=path[i][k]。path[i][j]中的值为i到j的最短路径中,i之后顶点的序号。由于此时k为中继点,则可以把路径分为2段,且path[i][j]=path[i][k]无疑问。
分析
时间复杂度为O(n.^3),空间复杂度为O(n.^2)
代码
//floyd算法求点之间的最短路径
void floyd(int adjMatrix[4][4],int path[4][4],int dist[4][4]){
for(int i=0;i<4;i++)
for(int j=0;j<4;j++){
path[i][j]=j;//初始化,表示i到j的路径的下一顶点
dist[i][j]=adjMatrix[i][j];//初始化
}
for(int k=0;k<4;k++){
for(int i=0;i<4;i++)
for(int j=0;j<4;j++){
if(i==k||j==k||i==j) continue;
if(dist[i][j]>dist[i][k]+dist[k][j]){
dist[i][j]=dist[i][k]+dist[k][j];//更新最短距离
path[i][j]=path[i][k];//更新路径
}
}
}
}
void main(){
int adjMatrix[4][4]={{0,1,100,4},{100,0,9,2},{3,5,0,8},{100,100,6,0}};
int path[4][4],dist[4][4];
floyd(adjMatrix,path,dist);
for(int i=0;i<4;i++)
for(int j=0;j<4;j++){
if(i!=j){
cout<<i<<"->"<<j<<": ";
if(dist[i][j]>=100)
cout<<"不存在路径"<<endl;
else{
cout<<"dist: "<<dist[i][j]<<",path: ";
int pre=i;
while(pre!=j){
cout<<pre<<"--";
pre=path[pre][j];
}
cout<<j<<endl;
}
}
}
}