本章是迪杰斯特拉算法的C++实现。

目录
1. 迪杰斯特拉算法介绍
2. 迪杰斯特拉算法图解
3. 迪杰斯特拉算法的代码说明
4. 迪杰斯特拉算法的源码

转载请注明出处:http://www.cnblogs.com/skywang12345/

更多内容:数据结构与算法系列 目录

迪杰斯特拉算法介绍

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。
它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

基本思想

通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。

此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。

初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是"起点s到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。

操作步骤

(1) 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。

(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。

(3) 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。

(4) 重复步骤(2)和(3),直到遍历完所有顶点。

单纯的看上面的理论可能比较难以理解,下面通过实例来对该算法进行说明。

迪杰斯特拉算法图解

以上图G4为例,来对迪杰斯特拉进行算法演示(以第4个顶点D为起点)。

初始状态:S是已计算出最短路径的顶点集合,U是未计算除最短路径的顶点的集合!
第1步:将顶点D加入到S中。
    此时,S={D(0)}, U={A(∞),B(∞),C(3),E(4),F(∞),G(∞)}。
    注:C(3)表示C到起点D的距离是3。

第2步:将顶点C加入到S中。
    上一步操作之后,U中顶点C到起点D的距离最短;因此,将C加入到S中,同时更新U中顶点的距离。以顶点F为例,之前F到D的距离为∞;但是将C加入到S之后,F到D的距离为9=(F,C)+(C,D)。
    此时,S={D(0),C(3)}, U={A(∞),B(23),E(4),F(9),G(∞)}。

第3步:将顶点E加入到S中。
    上一步操作之后,U中顶点E到起点D的距离最短;因此,将E加入到S中,同时更新U中顶点的距离。还是以顶点F为例,之前F到D的距离为9;但是将E加入到S之后,F到D的距离为6=(F,E)+(E,D)。
    此时,S={D(0),C(3),E(4)}, U={A(∞),B(23),F(6),G(12)}。

第4步:将顶点F加入到S中。
    此时,S={D(0),C(3),E(4),F(6)}, U={A(22),B(13),G(12)}。

第5步:将顶点G加入到S中。
    此时,S={D(0),C(3),E(4),F(6),G(12)}, U={A(22),B(13)}。

第6步:将顶点B加入到S中。
    此时,S={D(0),C(3),E(4),F(6),G(12),B(13)}, U={A(22)}。

第7步:将顶点A加入到S中。
    此时,S={D(0),C(3),E(4),F(6),G(12),B(13),A(22)}。

此时,起点D到各个顶点的最短距离就计算出来了:A(22) B(13) C(3) D(0) E(4) F(6) G(12)

迪杰斯特拉算法的代码说明

以"邻接矩阵"为例对迪杰斯特拉算法进行说明,对于"邻接表"实现的图在后面会给出相应的源码。

1. 基本定义

  1. class MatrixUDG {
  2. #define MAX 100
  3. #define INF (~(0x1<<31)) // 无穷大(即0X7FFFFFFF)
  4. private:
  5. char mVexs[MAX]; // 顶点集合
  6. int mVexNum; // 顶点数
  7. int mEdgNum; // 边数
  8. int mMatrix[MAX][MAX]; // 邻接矩阵
  9. public:
  10. // 创建图(自己输入数据)
  11. MatrixUDG();
  12. // 创建图(用已提供的矩阵)
  13. //MatrixUDG(char vexs[], int vlen, char edges[][2], int elen);
  14. MatrixUDG(char vexs[], int vlen, int matrix[][9]);
  15. ~MatrixUDG();
  16. // 深度优先搜索遍历图
  17. void DFS();
  18. // 广度优先搜索(类似于树的层次遍历)
  19. void BFS();
  20. // prim最小生成树(从start开始生成最小生成树)
  21. void prim(int start);
  22. // 克鲁斯卡尔(Kruskal)最小生成树
  23. void kruskal();
  24. // Dijkstra最短路径
  25. void dijkstra(int vs, int vexs[], int dist[]);
  26. // 打印矩阵队列图
  27. void print();
  28. private:
  29. // 读取一个输入字符
  30. char readChar();
  31. // 返回ch在mMatrix矩阵中的位置
  32. int getPosition(char ch);
  33. // 返回顶点v的第一个邻接顶点的索引,失败则返回-1
  34. int firstVertex(int v);
  35. // 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
  36. int nextVertex(int v, int w);
  37. // 深度优先搜索遍历图的递归实现
  38. void DFS(int i, int *visited);
  39. // 获取图中的边
  40. EData* getEdges();
  41. // 对边按照权值大小进行排序(由小到大)
  42. void sortEdges(EData* edges, int elen);
  43. // 获取i的终点
  44. int getEnd(int vends[], int i);
  45. };

MatrixUDG是邻接矩阵对应的结构体。
mVexs用于保存顶点,mVexNum是顶点数,mEdgNum是边数;mMatrix则是用于保存矩阵信息的二维数组。例如,mMatrix[i][j]=1,则表示"顶点i(即mVexs[i])"和"顶点j(即mVexs[j])"是邻接点;mMatrix[i][j]=0,则表示它们不是邻接点。

2. 迪杰斯特拉算法

  1. /*
  2. * Dijkstra最短路径。
  3. * 即,统计图中"顶点vs"到其它各个顶点的最短路径。
  4. *
  5. * 参数说明:
  6. * vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。
  7. * prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。
  8. * dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。
  9. */
  10. void MatrixUDG::dijkstra(int vs, int prev[], int dist[])
  11. {
  12. int i,j,k;
  13. int min;
  14. int tmp;
  15. int flag[MAX]; // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。
  16. // 初始化
  17. for (i = 0; i < mVexNum; i++)
  18. {
  19. flag[i] = 0; // 顶点i的最短路径还没获取到。
  20. prev[i] = 0; // 顶点i的前驱顶点为0。
  21. dist[i] = mMatrix[vs][i]; // 顶点i的最短路径为"顶点vs"到"顶点i"的权。
  22. }
  23. // 对"顶点vs"自身进行初始化
  24. flag[vs] = 1;
  25. dist[vs] = 0;
  26. // 遍历mVexNum-1次;每次找出一个顶点的最短路径。
  27. for (i = 1; i < mVexNum; i++)
  28. {
  29. // 寻找当前最小的路径;
  30. // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
  31. min = INF;
  32. for (j = 0; j < mVexNum; j++)
  33. {
  34. if (flag[j]==0 && dist[j]<min)
  35. {
  36. min = dist[j];
  37. k = j;
  38. }
  39. }
  40. // 标记"顶点k"为已经获取到最短路径
  41. flag[k] = 1;
  42. // 修正当前最短路径和前驱顶点
  43. // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
  44. for (j = 0; j < mVexNum; j++)
  45. {
  46. tmp = (mMatrix[k][j]==INF ? INF : (min + mMatrix[k][j]));
  47. if (flag[j] == 0 && (tmp < dist[j]) )
  48. {
  49. dist[j] = tmp;
  50. prev[j] = k;
  51. }
  52. }
  53. }
  54. // 打印dijkstra最短路径的结果
  55. cout << "dijkstra(" << mVexs[vs] << "): " << endl;
  56. for (i = 0; i < mVexNum; i++)
  57. cout << " shortest(" << mVexs[vs] << ", " << mVexs[i] << ")=" << dist[i] << endl;
  58. }

迪杰斯特拉算法的源码

这里分别给出"邻接矩阵图"和"邻接表图"的迪杰斯特拉算法源码。

1. 邻接矩阵源码(MatrixUDG.cpp)

2. 邻接表源码(ListUDG.cpp)

Dijkstra算法(二)之 C++详解的更多相关文章

  1. Floyd算法(二)之 C++详解

    本章是弗洛伊德算法的C++实现. 目录 1. 弗洛伊德算法介绍 2. 弗洛伊德算法图解 3. 弗洛伊德算法的代码说明 4. 弗洛伊德算法的源码 转载请注明出处:http://www.cnblogs.c ...

  2. Prim算法(二)之 C++详解

    本章是普里姆算法的C++实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http://www.cnblogs.com/sk ...

  3. Kruskal算法(二)之 C++详解

    本章是克鲁斯卡尔算法的C++实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3. 克鲁斯卡尔算法图解 4. 克鲁斯卡尔算法分析 5. 克鲁斯卡尔算法的代码说明 6. 克鲁斯卡尔算法的源码 转 ...

  4. Dijkstra算法(三)之 Java详解

    http://www.cnblogs.com/skywang12345/p/3711516.html

  5. 转:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法、shiro认证与shiro授权

    原文地址:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法.shiro认证与shiro授权 以下是部分内容,具体见原文. shiro介绍 什么是shiro shiro是Apache ...

  6. 二叉搜索树详解(Java实现)

    1.二叉搜索树定义 二叉搜索树,是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值: 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根 ...

  7. 数据结构图文解析之:二叉堆详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  8. Java进阶(三十二) HttpClient使用详解

    Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...

  9. Spring Boot 启动(二) 配置详解

    Spring Boot 启动(二) 配置详解 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Boot 配置 ...

随机推荐

  1. 自己做了一个json格式化工具,亲测可以使用

    随笔背景:在向后台请求数据之后,我们常常会拿到一串json格式.此时,为了方便查看key-value,程序猿们常常使用一些在线json格式化工具或者是类似于notepadd++这样的工具进行转换.今天 ...

  2. hdu 4193 - Non-negative Partial Sums(滚动数列)

    题意: 给定一个由n个整数组成的整数序列,可以滚动,滚动的意思就是前面k个数放到序列末尾去.问有几种滚动方法使得前面任意个数的和>=0. 思路: 先根据原来的数列求sum数组,找到最低点,然后再 ...

  3. halcon读取一张照片,并转化为灰度图像

    dev_close_window () read_image (Image, 'E:/图片/123.jpg') get_image_size (Image, Width, Height) dev_op ...

  4. 【leetcode】Merge Two Sorted Lists

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  5. java jps 命令详解

    JPS 名称: jps - Java Virtual Machine Process Status Tool 命令用法: jps [options] [hostid] options:命令选项,用来对 ...

  6. 作业二--注册GitHub的过程

    第一步:打开GitHub官网https://github.com/,在界面中输入账号名称.邮箱.密码,然后点击注册按钮. 第二步:注册完成后,选择Free免费账号完成初始设置. 第三步:验证邮箱,打开 ...

  7. [.net 面向对象编程基础] (18) 泛型

    [.net 面向对象编程基础] (18) 泛型 上一节我们说到了两种数据类型数组和集合,数组是指包含同一类型的多个元素,集合是指.net中提供数据存储和检索的专用类. 数组使用前需要先指定大小,并且检 ...

  8. redis(一) 安装以及基本数据类型操作

    redis(一) 安装以及基本数据类型操作 redis安装和使用 redis安装 wget http://download.redis.io/redis-stable.tar.gz tar zxvf ...

  9. SharePoint—用REST方式访问列表

    REST的定义与作用 在SharePoint 2010中,基本上有如下几种数据访问方式: 服务器端对象模型 LINQ to SharePoint Web Service 客户端对象模型 ADO.NET ...

  10. MR原理

    三.MapReduce运行原理 1.Map过程简述: 1)读取数据文件内容,对每一行内容解析成<k1,v1>键值对,每个键值对调用一次map函数 2)编写映射函数处理逻辑,将输入的< ...