关于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;
}

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

时间: 2024-10-12 02:33:06

关于dijkstra算法的一点理解的相关文章

dijkstra算法:寻找到全图各点的最短路径

dijkstra算法介绍:即迪杰斯特拉算法,是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止,是一种广度优先的搜索方法. dijkstra算法原理:最优子路径存在.假设从S→E存在一条最短路径SE,且该路径经过点A,那么可以确定SA子路径一定是S→A的最短路径.证明:反证法.如果子路径SA不是最短的,那么就必然存在一条更短的'SA,从而SE路径也就不是最短,与原假设矛盾. dijkstra算法缺点:与此前

Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解

1 /* 2 Dijkstra算法用优先队列来实现,实现了每一条边最多遍历一次. 要知道,我们从队列头部找到的都是到 3 已经"建好树"的最短距离以及该节点编号, 并由该节点去更新 树根 到其他点(被更新的节点可以在队列中 4 ,也可以是非队列中的节点)的距离 . 5 6 ////队列中的节点都是要等待更新的节点 7 8 如果某个节点从队列中出来的时候,如果cur.first != dist[cur.second] 就是 cur.second这个节点一开始 9 被更新的最短距离值 和

理解机器学习算法的一点心得

从Andrew ng的公开课开始,机器学习的算法我接触到的也越来越多,我觉得机器学习算法和传统算法的最大不同就是:不会要求一个问题被100%求解,也就意味着不会有完美的解法,这也是著名的"Essentially, all models are wrong, but some are useful."所表达的意思.正因为如此,机器学习算法往往不会有一个固定的算法流程,取而代之的把问题转化为最优化的问题,无论是ML(maximum likelihood),MAP(Maximum a Pos

关于Dijkstra 和 Bellman-ford算法的简单理解

两个算法都是跟求图的有源最短路径有关.Dijkstra主要针对的是无负权值节点的图,而Bellman-Ford算法则是可以处理有负权值的有向图的最短路径问题.两者都用到了一个"松弛计算"的方法,也就是在遍历图的顶点和边的过程中修改距离数组的值,从而来找出最短路径. Dijkstra算法针对无负权值的图,求源点到某特定点的最短距离.大概的思路是: 将图的顶点分成两个集合S,V.S中开始时只有源点,而V中是剩下的点.有一个dis[n](n为图的节点数)的数组来记录每一个点到源点的特殊距离,

最短路:我的理解--Dijkstra算法

最短路径:Dijkstra算法 用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法.也就是说,只能计算起点只有一个的情况. Dijkstra的时间复杂度是O (N2),它不能处理存在负边权的情况. 算法描述:        设起点为s,dis[v]表示从s到v的最短路径,pre[v]为v的前驱节点,用来输出路径.        a)初始化:dis[v]=∞(v≠s); dis[s]=0; pre[s]=0;        b)For (i = 1; i <= n-1 ; i++

658 - It&#39;s not a Bug, it&#39;s a Feature! (Dijkstra算法)

今天第一次系统的学习了一下最短路算法,开始刷第十一章,第一次写Dijkstra算法,出现了很多喜闻乐见的错误..而且uva上样例很水,瓢虫也很水 ,坑了我好久. 首先是对于结点的处理,我们必须要维护一个二元组,一个表示结点一个表示当前结点最短路.   因为Dijkstra算法利用了优先队列来加速算法,所以需要定义小于运算符,一开始我直接将状态装进了优先队列,显然是不对的,因为优先队列的作用就是取出当前距离最短的结点. 其次,说说最短路算法蕴含的巧妙思想: 每次从当前所有还未标记的结点中选择一个距

dijkstra算法 - 最短路径算法

2017-07-26 22:30:45 writer:pprp dijkstra算法法则:设置顶点集合S,首先将起始点加入该集合,然后根据起始点到其他顶点的路径长度, 选择路径长度最小的顶点加入到集合S,根据所加入顶点更新源点到其他顶点的路径长度,然后再选取最小边的顶点: 实现:用邻接矩阵 我的理解:从某一点出发,找到与该点临近有路径的点,找到其中最短路径的点,将其标记,表示已经访问过了, 然后更新距离的数组(如果通过两步路径和要比一步的路要短),还需要在深刻理解一下: 代码如下: #inclu

对于A星/Astar/A*算法的一些理解

A星算法是经常利用到搜寻最短路径的算法,而相对于各种spfa,dijkstra等最短路算法,其最大的优势就是以一种贪心式的方法来逼近最优值,而非像spfa,dijkstra算法的较为盲目的搜索. 虽然可能在特殊设计出来的图上效率会与spfa,dijkstra相比较低,但是随机生成的图中其效率可以远远高于最短路径算法. A星算法在我看来是一种spfa与dijkstra的组合改良. 無障礙 有障礙 (圖片取自 Amit's Thoughts on Path-Finding and A-Star) 注

路径搜索 &ndash; Dijkstra 算法 (MATLAB实现)

因为在上一门算法课(https://www.coursera.org/learn/robotics-motion-planning/home/welcome),看了老师的视频也不明白,又接着百度了一些关于这个算法的说明,各种大神写得很高深,很多专业术语,超出了我的认知水平,我看了很久也看不懂. 最后总算明白了一些些,于是,用大白话把它记录一下,免得下次又忘记了.要真要用这些搜索算法的话,还不如直接调用命令算了:http://www.mathworks.com/help/releases/R201