【算法复习】Dijkstra寻图的最小路径

在带非负权有向图中,提到求最短路径,Dijkstra算法是必然少不了的。而Dijkstra究竟能够怎样来求出最短路径,为了方便以后回顾,做一个比较。



Dijkstra算法适用于邻接矩阵的图的结构,采取贪心的方法,每次选取当前情况的最优解,逐级递进,以广度优先的模式先找出就近点的最小路径后,再往外扩,并且当发现有比已得结果更优的解的时候就进行修正。但这个算法只能解决某一个顶点到其他所有顶点的最短路径。如果要求另一顶点到其他顶点的最短路径,就需要再用这个算法重复一次。(因为是有向图)

算法的分析过程就不做论述了。

算法的过程描述:

(1)初始化:

    假设用arcs矩阵来表示带权有向图,arcs[i][j] 来表示顶点i到j的权值,如果i到j不存在,就赋一个其他值,这里用MAX来表示;

            数组final表示已找到从出发点(用户给予)的最短路径的终点的集合,初始用于表示出发点到索引对应的顶点的最短路径是否求出,除出发点外,其他都为false;

            数组D来表示从出发点(用户给)到其他点(相当于数组索引对应的点)的最短路径的长度。初值就是出发点那个点在arcs中那一行的权值;

循环

{

(2)求最短路径:

        找出当前点到最短到达的下一个点。


(3)修正:

遍历顶点路径数组,如果这个值大于(2)中求出的值加上(2)中点到这个遍历到的点的路径,把值赋过来。

伪代码形式 k: 0->最大顶点数  if D[j]+arcs[j][k] < D[k] 则  D[k]=D[j]+arcs[j][k]

   

}



#include <iostream>
#define MAX 65535
#define MAXVEX 20
using namespace std;
typedef struct
{
    int arcs[MAXVEX][MAXVEX];
    int vexnum,arcnum;
}MGraph;

void Dijkstra(MGraph &G,int v0,int* D,int* path)
{
        int i,j,k=0;                     //用于控制循环的变量,K则为编号暂存变量
        int final[MAXVEX];          //作为标记数组,用来标记索引对应编号的顶点是否已经获取到最小路径
        for(i=0;i<G.vexnum;i++)
        {
              D[i]=G.arcs[v0][i];		//D数组用来存放初始点到索引对应顶点编号的最短路径长度
              final[i] = false;
              if(D[i]!= MAX)                 //初始化。如果初始顶点到其他顶点有权值则指定前驱为初始点
                path[i]=v0;			// path数组是用来存放索引对应的顶点编号在最短路径中的前驱
              else
                path[i]=MAX;
        }
        final[v0]=true;             
        D[v0] =0;
        path[v0]=v0;                   //以上为初始化也即第(1)部分
        for(i=1;i<G.vexnum;i++)
        {
             int min = MAX;
             for(j=0;j<G.vexnum;j++)
                    if(D[j] < min && final[j] ==0)       
                    {
                        min = D[j];
                        k = j;
                    }
             final[k] = true;                       //找出最短路径,并将编号暂存于k
             for(j=0;j<G.vexnum;j++)
             {
                if(D[j]>min+G.arcs[k][j] &&final[j] ==0)
                {
                   D[j] = min+G.arcs[k][j];                 //修正结果,如果还有比这个路径更短的路径,则把更短路径的长度赋值过来
                   path[j]= k;
                }
             }
        }
}
int main()
{
        MGraph myGraph;
        int arcs[MAXVEX][MAXVEX] ={0};                      //为了方便测试,自己准备了组数据,重心在dijisktra算法,这部分不必在意
        arcs[0][2] = 10;
        arcs[0][4] = 30;
        arcs[0][5] = 100;

        arcs[1][2] = 5;
        arcs[2][3] = 50;
        arcs[3][5] = 10;
        arcs[4][3] = 20;
        arcs[4][5] = 60;
        for(int i =0;i<6;i++)
        {
                for(int j =0;j<6;j++)
                {
                        if(!arcs[i][j])
                                arcs[i][j] = MAX;
                        myGraph.arcs[i][j] = arcs[i][j];
                        cout<<myGraph.arcs[i][j]<<" ";
                }
                cout<<endl;
        }
        myGraph.vexnum = 6;
        int *dist = (int*)malloc(60);
        int *path = (int*)malloc(60);
        Dijkstra(myGraph,0,dist,path);
        for(int i =0;i<6;i++)
                cout<<dist[i]<<endl;
        for(int i=0;i<6;i++)
                cout<<path[i]<<endl;

return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值