最短路径之Dijkstra算法及实例分析

Dijkstra算法迪科斯彻算法

Dijkstra算法描述为:假设用带权邻接矩阵来表示带权有向图。首先引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点Vi的最短路径。它的初始状态为:若两顶点之间有弧,则D[i]为弧上的权值;否则置D[i]为无穷大。

1. 找到与源点v最近的顶点,并将该顶点并入最终集合S;

2. 根据找到的最近的顶点更新从源点v出发到集合V-S上可达顶点的最短路径;

3. 重复以上操作。

以前总是认为Dijkstra算法可以用来求从源点到指定终点的最短路径,导致总不能抓住算法的中心思想。现在认为把握Dijkstra的算法要点为:

1. Dijkstra提出了一个按路径长度递增的次序产生最短路径的算法;

2. 每次循环都可以得到一个从源点到某个顶点的最短路径,某个即不是确定的一个;

以 带权有向图 1为例说明Dijkstra算法的执行过程:

1  带权有向图

假设源点为v0,则初始状态时源点到其它各顶点的距离为:<∽代表无穷大>

源点 终点

v1

v2

v3

v4

v5

v0

10

30

100

由上表可知,与源点v0最近的顶点为v2,距离为10。

将v2加入到最终顶点集合S中。

再根据v2更新从源点到其它顶点的最短距离,即从v0-v2-v3的距离为60<∽,所以将v0到v3的距离更新为60,如下表所示:

源点 终点

v1

v2

v3

v4

v5

v0

10

60

30

100

由上表可知,与源点v0次近的顶点为v4,距离为30。

将v4加入到最终顶点集合S中;

再根据v4更新从源点到其它顶点的最短距离。即从v0-v4-v3的距离为50<60,所以将v0到v3的距离更新为50;从v0-v4-v5的距离为90<100,所以将v0到v5的距离更新为90。

源点 终点

v1

v2

v3

v4

v5

v0

10

50

30

90

重复以上操作……

直到最终集合包含了所有的顶点。

 

以上参考来源:http://www.cppblog.com/eryar/archive/2013/01/01/196897.html


>>应用例子:深大各地点之最短路径

#include<iostream>

#include<stack>

#include<string>

#defineM 100

#defineN 100

#definev_num 8  //顶点个数

#definee_num 11 //边数

usingnamespace std;

 

classMGraph

{

public:

       string name[v_num];           //顶点名称

       string info[v_num];         //顶点信息

    int matrix[N][M];      //邻接矩阵

    int n ;                 //顶点数

    int e ;                 //边数

public:

       MGraph(int v_n,int e_n){ n = v_n; e =e_n; }

       void help();

       void buildMap();

       void buildInfo();

       void display();

       void findInfo(int v);

       void findDij(int v0,int v);

};

//主菜单

voidhelp() 

{

    cout<<"************************************"<<endl;

     cout<<"<1> 查询景点介绍\n";

     cout<<"<2> 查询任意两个景点之间的最佳路线\n";

     cout<<"<other> 退出\n";

    cout<<"************************************"<<endl;

}

//景点距离

voidMGraph::buildMap()

{

       matrix[0][1] = 5;

       matrix[1][3] = 5;

       matrix[1][2] = 8;

       matrix[2][3] = 5;

       matrix[3][4] = 5;

       matrix[4][5] = 4;

       matrix[4][6] = 10;

       matrix[3][6] = 10;

       matrix[5][6] = 10;

       matrix[5][7] = 20;

       matrix[6][7] = 15;

}

//景点名称及介绍信息

voidMGraph::buildInfo()

{

       name[0] = "南区";info[0] ="南区有学生宿舍以及新建的信工,机电,医学院大楼";

       name[1] = "学生活动中心/石头坞"; info[1] = "各种学生活动的主要场所";

       name[2] = "南图";info[2] = "南图书馆与北图书馆相对而立,主要存放理工科类书籍";

       name[3] = "教学楼";info[3] ="顾名思义,很多课程都在这上,建筑呈之字形,分A,B,C,D四栋";

       name[4] = "北图";info[4] ="北图书馆文学气息浓厚,主要存放文科类书籍";

       name[5] = "办公楼";info[5] ="深圳大学的行政办公楼";

       name[6] = "科技楼";info[6] ="又被称为中指楼,深大最具特色的建筑,兼具办公,科研";

       name[7] = "文科楼";info[7] ="文科楼是深大学生主要上课的场所之一";

}

//显示景点

voidMGraph::display() 

{

     int i;

    cout<<"*******************************菜单**********************************"<<endl;

        cout<<"*********************************************************************"<<endl;

     cout<<"<0>返回上层菜单       ";

     for(i=0;i<v_num;++i)

     {  

         if((i+2)%3==0)

               {

           cout<<'<'<<i+1<<'>'<<name[i]<<endl;

                     cout<<"---------------------------------------------------------------------"<<endl;

               }

         else

           cout<<'<'<<i+1<<'>'<<name[i]<<"                ";

     }   

        cout<<endl;

    cout<<"*********************************************************************"<<endl<<endl;

}

//查询景点信息

voidMGraph::findInfo(int v)

{

       cout<<"-------------------------<"<<name[v]<<">------------------------------"<<endl;

       cout<<endl;

    cout<<info[v]<<endl;

   cout<<"---------------------------------------------------------------------"<<endl;

       cout<<endl<<endl;

}

 

//最短路径算法

voidMGraph::findDij(int v0,int v)   //v0表示源顶点

{

       int *dist=(int *)malloc(sizeof(int)*n);

    int *path=(int *)malloc(sizeof(int)*n);

    int i,j,k;

    bool *visited=(bool*)malloc(sizeof(bool)*n);

    for(i=0;i<n;i++)     //初始化

    {

        if(matrix[v0][i]>0&&i!=v0)

        {

            dist[i]=matrix[v0][i];

            path[i]=v0;     //path记录最短路径上从v0到i的前一个顶点

        }

        else

        {

            dist[i]=INT_MAX;    //若i不与v0直接相邻,则权值置为无穷大

            path[i]=-1;

        }

        visited[i]=false;

        path[v0]=v0;

        dist[v0]=0;

    }

    visited[v0]=true;

    for(i=1;i<n;i++)     //循环扩展n-1

    {

        int min=INT_MAX;

        int u;

        for(j=0;j<n;j++)    //寻找未被扩展的权值最小的顶点

        {

           if(visited[j]==false&&dist[j]<min)

            {

                min=dist[j];

                u=j;       

            }

        }

        visited[u]=true;

        for(k=0;k<n;k++)   //更新dist数组的值和路径的值

        {

           if(visited[k]==false&&matrix[u][k]>0&&min+matrix[u][k]<dist[k])

            {

                dist[k]=min+matrix[u][k];

                path[k]=u;

            }

        }       

    }   

 

       //输出最短路线

       cout<<endl<<name[v0]<<"到"<<name[v]<<"的最短路径是:"<<dist[v]<<endl;

       //打印路线

       stack<int> s;

    int u=v;

    while(v!=v0)

    {

        s.push(v);

        v=path[v];

    }

    s.push(v);

       cout<<"具体路线为:";

    while(!s.empty())

    {

        cout<<name[s.top()]<<"";

        s.pop();

    }

       cout<<endl<<endl;

}

 

 

//主函数

intmain(int argc, char *argv[])

{

          int i,j,c2;

              char c1;

        MGraph g(v_num,e_num);

             

        int v0,v;

       

        for(i=0;i<N;i++)

            for(j=0;j<M;j++)

                g.matrix[i][j]=10000;

      

              g.buildInfo();

              g.buildMap();

             

              do

              {

                     help();

                     cout<<"请选择查询内容:"<<endl;

                     cin>>c1;

                     switch(c1)

                     {

                       case'1':while(1)

                                     {

                                           g.display();

                                           cout<<"请输入查询景点编号:"<<endl;

                                           cin>>c2;

                                           if(c2==0) break;

                                           g.findInfo(c2-1);

                                     }

                                     break;

                       case'2':while(1)

                                     {

                                           g.display();

                                           cout<<"请依次输入两个查询景点编号(第一个编号小于第二个):"<<endl;

                                           cin>>v0>>v;

                                           if(v0==0||v==0)  break;

                                           g.findDij(v0-1,v-1);

                                     }

                                     break;

                     }

               }while(c1=='1'||c1=='2');

   

    return 0;

}







转载于:https://www.cnblogs.com/hisheng/p/6134984.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值