zoukankan      html  css  js  c++  java
  • 关于dijkstra算法的一点理解

      最近在准备ccf,各种补算法,图的算法基本差不多看了一遍。今天看的是Dijkstra算法,这个算法有点难理解,如果不深入想的话想要搞明白还是不容易的。弄了一个晚自习,先看书大致明白了原理,就根据书上的代码敲,边敲边深入思考,第一遍敲完运行失败,然后回过头在分析代码,改进还是失败。经过三次修改总算勉强跑起来了,但是结果还是不对,找了半天也找不出来。感觉整个人都不好了,弄了快三个小时结果还是有问题。时间差不多就回宿舍,在路上边走边想终于找到自己代码的问题了,回到宿舍代码修改后终于完美运行。经过一晚上的不断思考深入,反复推敲,得到了完美结果,付出和回报是成正比的。

      好了!大致讲一下自己对这个算法的理解吧!首先要想弄明白这个算法还是得了解一下广度优先搜索的原理,这个算法就是基于广搜的原理得出来的一个算法。算法的核心又有点贪心算法的味道,所以说这个算法相当经典。Dijkstra算法是求单个节点到图中其他所有节点的最短距离,为了解决这个问题,首先要引入三个数组D[i](记录起始点到其他各点的最短距离),mark[i](表示每个节点的是否已经访问过),p[i](记录每个节点的前驱结点,便于观察最后到各个顶点的路径)。

      Dijkstra算法的执行步骤:1.先初始化D[i]=v与i之间的距离(若两点不相连则为INIFY),mark[i]=0,p[i]=0,并将起始节点v的mark[v]=0;

                  2.遍历剩余的节点,找出剩余节点与v之间的距离(初始状态下除去相连的节点间有距离外其余所有节点间距离为INIFY),不相连的节点依然设为INIFY不变。找出其中与v距离最小的那个点k,mark[k]=1;

                   3.遍历所有节点,对其中mark[i]==0的点与k点的距离+2中的那个最小距离与D[i]比较,若小于D[i]则更新D[i],并将p[i]标记为k(k为该节点的前驱)。

                 4.遍历完后得到的D[i]就是v到各个节点的最短距离.

    #include<iostream>
    
    using namespace std;
    #define INFTY 10000
    
    class Graph
    {
    public:
        Graph(int n);        //构造函数初始化 
        ~Graph();            //析构函数销毁 
        void SetEdge(int v1,int v2,int weight);        //设置图中的相连边及其权值
        void Dijkstra(int v0);        //迪杰斯特拉算法 
        void Print(); 
    private:
        int numVex;            //顶点数 
        int numEdge;        //边数 
        int **matrix;        //
        int *mark;            //顶点标记 
        int *p;                //表示PathMatrix最短路径的前驱结点 
        int *D;                //表示ShortPathTa即两点间的带权长度 
    };
    
    Graph::Graph(int n)
    {
        numVex=n;
        numEdge=0;
        mark=new int[numVex];
        p=new int[numVex];
        D=new int[numVex]; 
        matrix=new int*[numVex];
        for(int i=0;i<numVex;i++)
        {
            matrix[i]=new int[numVex];
        }
        for(int i=0;i<numVex;i++)
        {
            mark[i]=0;
            p[i]=0;
            D[i]=0;
        }
        for(int i=0;i<numVex;i++)
        {
            for(int j=0;j<numVex;j++)
            {
                matrix[i][j]=matrix[j][i]=INFTY;
            }
        }
    } 
    
    Graph::~Graph()
    {
        delete []p;
        delete []D;
        delete []mark;
        for(int i=0;i<numVex;i++)
        {
            delete []matrix[i];
        }
        delete []matrix;
    }
    
    void Graph::SetEdge(int v1,int v2,int weight)
    {
        matrix[v1][v2]=matrix[v2][v1]=weight;
    }
    
    void Graph::Dijkstra(int v0)
    {
        int k,min;
        for(int i=0;i<numVex;i++)
        {
            D[i]=matrix[v0][i];
        }
        D[v0]=0;     
        mark[v0]=1;        //表示已经求得v0点的最短路径 
        for(int i=1;i<numVex;i++)
        {
            min=INFTY;
            for(int j=0;j<numVex;j++)
            {
                if(!mark[j] && D[j]<min)
                {
                    k=j;
                    min=D[j];
                }
            }
            mark[k]=1;    //表示从v0到k已经找到最短路径 
    
            //修正目前的最短路径 
            for(int j=0;j<numVex;j++)
            {
                if(!mark[j] && (min+matrix[k][j]<D[j]))
                {
                    D[j]=min+matrix[k][j];    //修改当前路径的长度 
                    p[j]=k;            //存放当前节点的前驱 
                }
            }
        }
    }
    
    void Graph::Print()
    {
        cout<<"v0到各顶点的最短距离:"<<endl;
        for(int i=0;i<numVex;i++)
        {    
            cout<<D[i]<<" ";
        }
        cout<<endl;
        cout<<"各顶点的前驱顶点:"<<endl;
        for(int i=0;i<numVex;i++)
        {    
            cout<<p[i]<<" ";
        }
    }
    
    int main()
    {
        int n,m,t;
        cout<<"请输入顶点数n和边数m"<<endl;
        cin>>n>>m;
        Graph G(n);
        int v1,v2,weight;
        cout<<"请输入顶点v1,v2及两顶点间边的权值"<<endl;
        for(int i=0;i<m;i++)
        {
            cin>>v1>>v2>>weight;
            G.SetEdge(v1,v2,weight);
        }
        cout<<"请输入迪杰斯特拉算法的起始顶点"<<endl;
        cin>>t; 
        G.Dijkstra(t);
        G.Print();
        
        return 0;
    }

      代码自己写的,可以完美运行!希望对大家有帮助。

  • 相关阅读:
    Linux关闭jetty服务器脚本
    TreeMap 源码解读
    LinkedHashMap 源码解读
    HashTable 源码解读
    MappedByteBuffer文件句柄释放问题
    HashMap源码解读
    Java 对象创建过程
    java 虚拟机内存介绍
    dubbo 部署
    kotlin 学习入门
  • 原文地址:https://www.cnblogs.com/wenyi1992/p/6147887.html
Copyright © 2011-2022 走看看