数据结构与算法笔记——最短路径问题

897 阅读3分钟

1、总述

最短路径问题是基于图的应用,下面介绍的是几种求最短路径问题的方法和适用的场景,本文框架如下

2、基于单源最短路径  

单源最短路径即求图中某一顶点到其他格顶点的最短路径,主要介绍两种算法,一是基于图的广度优先搜索遍历算法(BFS),二是Dijkstra算法

2.1 基于图的广度优先算法(BFS)

2.1.1算法思想

若图G=(V,E)为非带权图,定义从顶点u 到顶点v的最短路径d(u,v)为从u到v的任何路径中最少的边数;若从u到v没有通路,则d(u,v)=无穷 BFS适用于无权图

使用BFS,我们可以求解一个满足上述定义的非带权图单源最短路径问题,这是由广度优先搜索总是按照距离由近到远来遍历图中每个顶点的性质来决定的

2.1.2 代码实现

d[]数组是用来标记指定顶点到其他顶点的距离,path[]数组用来标记路径


//求顶点u到其他顶点的最短路径
void BFS_MIN_Distance(Graph G,int u){
//d[i]表示从u到i节点的最短路径
  for(i=0;i<G.vexnum;++i){
    d[i]= INF;  //初始化路径长度你,为最大值
    path[i]=-1;  //最短路径从那个顶点过来
  }

d[u]=0;
visited[u]=true;
EnQueue(Q,u);
while(!isEmpty(Q)){        //BFS算法主过程
DeQueue(Q,u);              //队头元素出队
for(w=FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w)){

    if(!visited[w]){       //w为u尚未访问的邻接顶点
        d[w]=d[u]+1;       //路径长度加1
        path[w]=u;         //最短路径应从u到w
        visited[w]=true;   //设已访问标记
        EnQueue(Q,w);       //顶点w入队
    }//if
  }//for
 }//while

}

2.1.3 运行结果

我们以下图为例,从2号节点开始找它的单源最短路径

2.2、Dijkstra算法

Dijkstra算法可用于求带权图的单源最短路径问题边上带有负权值时,Dijkstra算法不适用

2.2.1代码实现

void Dijkstra(MGraph g,int v,int dist[],int path[]){
 int Set[maxSize];
 int Min,i,j,u;
 //初始化
 for(i=0;i,g.n;++i){
    dist[i]=g.edges[v][i];
    Set[i]=0;
    if(g.edges[v][i]<INF)
        path[i]=v;
    else
        path[i]=-1;
    
 }
 Set[v]=1;path[v]=-1;
 //初始化结束
 //关键操作开始
 for(i=0;i<g.n-1;++i){
    Min = INF;
    for(j=0;j<g.n;++j){
        /*这个循环每次从剩余节点中选出一个顶点,通往这个顶点的路径在通往所有剩余顶点的路径中是最短的*/
        if(Set[j]==0&dist[j]<Min){
        u=j;
        Min=dist[j];
     }
    }
    
    Set[u]=1;//将选出的顶点并入最短路径中
    
    for(j=0;j<g.n;++j){
        //这个循环以刚并入的顶点为中间节点,对所有通往剩余顶点的路径进行检测
        if(Set[j]==0&&dist[u]+g.edges[u][j]<dist[j]){
          //这个if语句判断顶点u的加入是否会出现通往顶点j的更短路径,如果出现,则改变原来的路径及其长度,否则什么都不做
            dist[j]=dist[u]+g.edges[u][j];
            path[j]=u;
        }//end if
    }
 }
 //关键操作结束
 }
 /*函数结束时,dist[]数组中存放了v点到其余顶点的最短路径长度,path[]中存放v点到其余个顶点的最短路径*/
 

2.2.2 运行结果

dist[]数组和path[]数组的变化情况如下