最短路径
定义
最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。 算法具体的形式包括:
确定起点的最短路径问题 - 即已知起始结点,求最短路径的问题。
确定终点的最短路径问题 - 与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。
确定起点终点的最短路径问题 - 即已知起点和终点,求两结点之间的最短路径。
全局最短路径问题 - 求图中所有的最短路径。
求最短路径的算法
DFS----点到点
用深度优先遍历的方式求点到点的最短路径
//ibeg,iend的最小距离 现在到了icurr点 currpath现在已经经过了多长的距离
void dfs_path(ALGraph *pg,int icurr,int iend,
int *pminpath,int currpath,bool visited[]){
if(icurr==iend){
if(currpath < *pminpath){
*pminpath = currpath;
}
return;
}
ArcNode *node = pg->vexs[icurr].firstarc;
for(;node!=NULL;node=node->next){
if(!visited[node->adjvex] && currpath + node->weight < *pminpath){
visited[node->adjvex] = true;
dfs_path(pg,node->adjvex,iend,pminpath,currpath+node->weight,visited);
visited[node->adjvex] = false;
}
}
}
//求beg,end顶点的最短路径
int dfs_min_path(ALGraph *pg,char beg,char end){
int ibeg = graph_get_index(pg,beg);
int iend = graph_get_index(pg,end);
if(ibeg==-1||iend==-1)
return -1;
if(ibeg==iend)
return 0;
int minpath = MAX_INT;//记录最短路径的值
int currpath = 0; //找的过程中,经过的多长距离
bool visited[pg->vexnum];
int i;
for(i=0;i<pg->vexnum;i++)
visited[i] = false;
visited[ibeg] = true;
dfs_path(pg,ibeg,iend,&minpath,0,visited);
return minpath;
}
floyd—所有点到所有点
算法思想
通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。
从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。
采用松弛技术(松弛操作),对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3);
算法过程
1,从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
2,对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。
把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=无穷大。定义一个矩阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j] = min( G[i,j], G[i,k]+G[k,j] ),如果G[i,j]的值变小,则D[i,j]=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。
void floyd(ALGraph *