zoukankan      html  css  js  c++  java
  • 最短路径之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> 查询景点介绍 ";

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

         cout<<"<other> 退出 ";

        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;

    }







  • 相关阅读:
    python计算机基础
    计算机基础知识
    ftok函数
    可重入函数与不可重入函数
    Redis学习资料整理
    小记6月18
    libxml2简单的生成、解析操作
    切换日志是否更新检查点?
    第五课 数据备份恢复实验
    第四课 Grid Control实验 GC Agent安装(第一台机器部署) 及卸载
  • 原文地址:https://www.cnblogs.com/hisheng/p/6134984.html
Copyright © 2011-2022 走看看