C++用Dijkstra(迪杰斯特拉)算法求最短路径

算法介绍

迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。

算法思想

按路径长度递增次序产生算法:

 把顶点集合V分成两组:

  (1)S:已求出的顶点的集合(初始时只含有源点V0)

  (2)V-S=T:尚未确定的顶点集合
  将T中顶点按递增的次序加入到S中,保证:

  (1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度

  (2)每个顶点对应一个距离值

  S中顶点:从V0到此顶点的长度

  T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度

  依据:可以证明V0到T中顶点Vk的,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和

应用举例

(1)题目:编写一个校园导游程序,为来访的客人提供各种信息查询服务。

    主要功能:1.设计学校的校园平面图,所含景点不少于10个:顶点表示景点,边表示路径等;

         2.为客人提供图中任意景点相关信息的查询;

         3.为客人提供图中任意景点的问路查询,即查询人以景点间的一条最短路径。

      要求:1.设计一个主界面;

              2.设计功能菜单,供用户选择

              3.有一定的实用性。

(2)设计思路:

  1、该题主要有算法思路以及程序的逻辑思路,首先从逻辑思路讲,进入程序,首先设计一个主菜单,选项有景点信息查询,最短路径查询以及显示景点的平面视图三个子菜单,然后根据用户的输入选择的子菜单前的编号,分进入不同的子菜单;该功能是由if….else if…. 语句实现。在景点信息查询和最短路径查询子菜单下还有二级子菜 单,都是列 出所有景点并在前面编号,查询景点信息时,输入景点前面的编号即可,查询最短路径时,先输入起点的编号,再输入终点的编号。而显示景点视图则调用景点平面图函数即可显 示。

  2、算法思路主要是迪杰斯特拉算法的思路,利用迪杰斯特拉算法求最短路径。

  3、先定义好图的储存结构,本题采用邻接矩阵的方式来表示图,并在主函数中初始化该图;

  4、定义三个全局一维数组,一个bool类型数组S[]用来记录从v0到vi是否已经确定了最短路径,是则记S[i]=true ,否记S[i]= flase;一个int 类型数组Path[]用来记录从v0到vi的当前最短路径上的vi的直接前驱顶点编号,若v 到vi之间有边则记Path[i] = v的编号,否则记Path[i] = -1;最后一个数组D[]用来记录从v0到vi之间的最短路径长度,存在则记v0到vi之间边的权值或者权值和,否则记为MAX

  5、定义一个求最短路径的函数,传入的参数为图和起点,首先进行初始化工作,初始化S[]数组全为false,D[]数组初始化为起点到各个顶点的权值,Path[]数组初始化为起点是否与各顶点有边,有则记v0否则记-1;

  6、然后进行n-1次for循环,找出vo到其余n-1个顶点之间的最短路径,比较当前D[]数组中最小值,找到最小值的编号v,该编号就是从v0出发到所有顶点中距离最短的顶点编号,然后把S[v]的值置为true。说明从v0出发到顶点v已经找到最短路径;

  7、接着就要更新D[]数组,因为D[]数组是记录最短路径的,现在已经找到了一个顶点的最短路径,已该顶点v为中间点,判断从该顶点v出发到剩下的顶点的路径长度加上该点到v0的路径长度是否小于直接从v0出发到其余顶点的路径长度,如果小于,则更新D[i]为以该顶点v为中间点求得的路径长度。更新Path[i] = v;即i的前驱不再是v0而是v;

  8、循环(6)(7)两步n-1次即可得到D[]数组,输出D[]数组既是v0到所有顶点的最短路径长度;

(3)源代码:

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
/**
 *作者:Dmego
 *时间:2016-12-12
 */
#define MAX 1000000 //表示极大值∞
#define max 10
bool S[max]; //记录从源点V0到终点Vi是否已经确定为最短路径,确定了记true,否则记false
int Path[max]; //记录从源点V0到终点Vi的当前最短路径上终点Vi的直接前驱顶点序号,若V0到Vi之间有边前驱为V0否则为-1
int D[max]; //记录源点到终点之间最短路径的长度,存在记V0到Vi的边的权值,否则记为MAX
typedef struct
{
 string vexs[max]; //顶点表
 int arcs[max][max]; //邻接矩阵
 int vexnum, arcnum; //图当前点数和边数

}AMGraph;
//利用迪杰斯特拉算法求最短路径
void ShortestPath_DIJ(AMGraph &G, int v0)
{//使用迪杰斯特拉算法求有向网G中的V0 定点到其余顶点的最短路径
 int n = G.vexnum;//顶点数
 for (int v = 0; v < n; v++)//n个顶点依次初始化
 {
 S[v] = false;//S初始化为空集
 D[v] = G.arcs[v0][v];//将v0到各个终点的最短路径长度初始化为边上的权值
 if (D[v] < MAX)
  Path[v] = v0;//如果v0和v之间有边,则将v的前驱初始化为v0
 else
  Path[v] = -1;//如果v0和v之间无边,则将v的前驱初始化为-1
 }
 S[v0] = true; //将v0加入s
 D[v0] = 0;//源点到源点的权值为0
 //---------初始化结束,开始主循环,每次求得v0到某个顶点的最短路径,将v加到S数组
 for (int i = 1; i < n; i++)//依次对其余n-1个顶点进行计算
 {
 int min = MAX;
 int v = v0;
 for (int w = 0; w < n; w++)
 {
  if (!S[w] && D[w] < min)
  {//选择一条当前最短路径,终点为v
  v = w;
  min = D[w];
  }
  S[v] = true;//将v加到s集合中
  for (int w = 0; w < n; w++)
  {//更新从v0出发到集合V-S上所有顶点的最短路径长度
  if (!S[w] && (D[v] + G.arcs[v][w] < D[w]))
  {
   D[w] = D[v] + G.arcs[v][w];//更新D[w]
   Path[w] = v;//更改w的前驱为v
  }
  }
 }
 }
}
//背景函数
void backGround()
{
 cout << "|*****************************************************************|" << endl;
 cout << " |------------------------铁大旅游景点图-----------------|" << endl;
 cout << "|*****************************************************************|" << endl;
 cout << "|  ⑦      单位:米 |" << endl;
 cout << "|  九教       |" << endl;
 cout << "|  ◎     ⑧  |" << endl;
 cout << "|       九栋  |" << endl;
 cout << "| ③ 200╱ ╲     ◎  |" << endl;
 cout << "| 西  ╲ 150       |" << endl;
 cout << "| 操 ◎  ╲ ①  160 ╱ ╲ 200 |" << endl;
 cout << "| 场 150  ╲ 信息  ⑥ ╱  ╲ |" << endl;
 cout << "| ④  140  学院 200 基教  230  |" << endl;
 cout << "| 体育馆 ◎-------------→◎←--------------→◎←--------------→◎ |" << endl;
 cout << "|          ② |" << endl;
 cout << "|  100 ╲ ╱ ╲ 125 ╱ ╲ 150 ╱ 综 |" << endl;
 cout << "|    100 ╲ ╱135 ╲ ╱145 餐 |" << endl;
 cout << "|   ◎       |" << endl;
 cout << "|  ⑨ 沁园  ◎   ◎  |" << endl;
 cout << "|    ⑩ 翠园  ⑤ 春晖楼  |" << endl;
 cout << "|        |" << endl;
 cout << "|*****************************************************************|" << endl;

}
//主菜单
void menu()
{
 cout << "|*****************************************************************|" << endl;
 cout << "|----------------------------铁大导游小程序-----------------------|" << endl;
 cout << " |*********************************************************|" << endl;
 cout << " |--------------------1-景点信息查询--------------|" << endl;
 cout << " |--------------------2-最短路径查询--------------|" << endl;
 cout << " |--------------------3-显示景点视图--------------|" << endl;
 cout << " |-------------------4-退出导游程序------ --------|" << endl;
 cout << "|*****************************************************************|" << endl;
 cout << ">>>请选择:";
}
//景点信息查询二级菜单
void jmenu()
{
 cout << "|*****************************************************************|" << endl;
 cout << " |-------------------------景点信息查询------------------------|" << endl;
 cout << " |***********************************************************|" << endl;
 cout << " |----------------------1-信息学院介绍-------------------| " << endl;
 cout << " |----------------------2-综合餐厅介绍-------------------| " << endl;
 cout << " |----------------------3-西操场介绍---------------------| " << endl;
 cout << " |----------------------4-体育馆介绍---------------------| " << endl;
 cout << " |----------------------5-春晖楼介绍---------------------| " << endl;
 cout << " |----------------------6-基教介绍-----------------------| " << endl;
 cout << " |----------------------7-九教介绍-----------------------| " << endl;
 cout << " |----------------------8-九栋介绍-----------------------| " << endl;
 cout << " |----------------------9-沁园介绍-----------------------| " << endl;
 cout << " |---------------------10-翠园介绍-----------------------| " << endl;
 cout << "|*****************************************************************|" << endl;
 cout << ">>>请要查询的景点编号:";
}
//最短路径查询二级菜单
void pmenu()
{
 cout << "|*****************************************************************|" << endl;
 cout << " |-------------------------最短路径查询------------------------|" << endl;
 cout << " |***********************************************************|" << endl;
 cout << " |---------------------1-信息学院-------------------| " << endl;
 cout << " | --------------------2-综合餐厅-------------------| " << endl;
 cout << " |---------------------3-西操场---------------------| " << endl;
 cout << " |---------------------4-体育馆---------------------| " << endl;
 cout << " |---------------------5-春晖楼---------------------| " << endl;
 cout << " |---------------------6-基教-----------------------| " << endl;
 cout << " |---------------------7-九教-----------------------| " << endl;
 cout << " |---------------------8-九栋-----------------------| " << endl;
 cout << " |---------------------9-沁园-----------------------| " << endl;
 cout << " |--------------------10-翠园-----------------------| " << endl;
 cout << "|*****************************************************************|" << endl;
 cout << ">>>请依次输入起点编号和终点编号:";
}
void main()
{
 //初始化操作
 AMGraph amg = { { "信息学院","综合餐厅","西操场","体育馆","春晖楼",
   "基教", "九教", "九栋", "沁园", "翠园" },
 //-1代表两边不相连,权值无限大
 //邻接矩阵 /* 信 综 西 体 春 基 教 栋 沁 翠*/
   {{MAX,MAX,MAX,140,MAX,200,150,MAX,100,125 },
   {MAX,MAX,MAX,MAX,145,230,MAX,100,MAX,MAX },
   {MAX,MAX,MAX,150,MAX,MAX,200,MAX,MAX,MAX },
   {140,MAX,150,MAX,MAX,MAX,MAX,MAX,100,MAX },
   {MAX,145,MAX,MAX,MAX,150,MAX,MAX,MAX,MAX },
   {200,230,MAX,MAX,150,MAX,MAX,160,MAX,135 },
   {150,MAX,200,MAX,MAX,MAX,MAX,MAX,MAX,MAX },
   {MAX,200,MAX,MAX,MAX,160,MAX,MAX,MAX,MAX },
   {100,MAX,MAX,100,MAX,MAX,MAX,MAX,MAX,MAX },
   {125,MAX,MAX,MAX,MAX,135,MAX,MAX,MAX,MAX }
   },10,14};
 int f, ff;
 int start, end;
 while (true)
 {
 cout << endl;
 menu();
 cin >> f;
 if (f == 1)
 {
  jmenu();
  cin >> ff;
       //景点信息从文件中读取
  ifstream outfile("schooltravel.txt", ios :: out | ios :: binary);
  if (!outfile)
  {
  cerr << "读取景点介绍文件失败!" << endl;
  abort();
  }
  string str[max];
  int i = 0;
  while (getline(outfile, str[i++]));
  cout << "|-----------------------景点介绍-------------------| " << endl;
  if (ff == 1)
  cout << str[0] << endl;
  else if (ff == 2)
  cout << str[1] << endl;
  else if (ff == 3)
  cout << str[2] << endl;
  else if(ff == 4)
  cout << str[3] << endl;
  else if (ff == 5)
  cout << str[4] << endl;
  else if (ff == 6)
  cout << str[5] << endl;
  else if (ff == 7)
  cout << str[6] << endl;
  else if (ff == 8)
  cout << str[7] << endl;
  else if (ff == 9)
  cout << str[8] << endl;
  else if (ff == 10)
  cout << str[9] << endl;
  cout << "|-------------------------------------------------|" << endl;
 }
 else if (f == 2)
 {
  pmenu();
  cin >> start >> end;
  ShortestPath_DIJ(amg, start - 1);
  int temp = end-1;
  int temp1, temp2;
  int flag[max], m = 0;
  cout << "从" << amg.vexs[start - 1] << "到" << amg.vexs[end - 1] << "最短路径为:" ;
  while (temp!= -1)
  {
  flag[m++] = temp;
  temp1 = temp ;
  temp2 = Path[temp1];
  temp = temp2;
  }
  for (int i = m-1; i >= 0; i--)
  {
  cout <<amg.vexs[flag[i]] << "->";
  }
  cout << endl;
  cout << "最短路径值为:" << D[end - 1] <<"米"<< endl;
 }
 else if (f == 3)
 {
  backGround();
 }
 else if (f == 4)
 {
  cout << ">>>退出成功!" << endl;
  exit(0);
 }
 }
}

(4)运行截图:

总结

以上就是关于C++用Dijkstra算法(迪杰斯特拉算法)求最短路径的全部内容了,希望本文的内容对大家的学习或者工作带来一定的帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • C++计算图任意两点间的所有路径

    基于连通图,邻接矩阵实现的图,非递归实现. 算法思想: 设置两个标志位,①该顶点是否入栈,②与该顶点相邻的顶点是否已经访问. A 将始点标志位①置1,将其入栈 B 查看栈顶节点V在图中,有没有可以到达.且没有入栈.且没有从这个节点V出发访问过的节点 C 如果有,则将找到的这个节点入栈,这个顶点的标志位①置1,V的对应的此顶点的标志位②置1 D 如果没有,V出栈,并且将与v相邻的全部结点设为未访问,即全部的标志位②置0 E 当栈顶元素为终点时,设置终点没有被访问过,即①置0,打印栈中元素,弹出栈顶

  • C++实现多源最短路径之Floyd算法示例

    本文实例讲述了C++实现多源最短路径之Floyd算法.分享给大家供大家参考,具体如下: #include<cstdio> #include<cstring> #include<iostream> #define MAX 999 using namespace std; int n,m; int e[MAX][MAX]; void Init() { for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) { if(i==

  • C++实现查找二叉树中和为某一值的所有路径的示例

    从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径. 打印出和与输入整数相等的所有路径. 例如 输入整数22和如下二元树 则打印出两条路径:10, 12和10, 5, 7. 先序遍历树即可得到结果. 算法: FindPath(BTree * root,int sum,int target,Stack * s) 用来计算,sum为栈中的元素的和,target为目标值. 到达一个节点之后计算当前节点和sum的和,如果为target,输出路径返回,如果大于target,则直接返回,如果小

  • c++查询最短路径示例

    复制代码 代码如下: //shortest_path.c#include<stdio.h>#include<stdlib.h>//用file#include<string.h>//可用gets(),puts()#include"shortest_path.h"#define MAX 32767#define MENU "欢迎进入导航系统!\n==========菜单===========\n0.载入北外地图\n1.建立地图\n2.查询最短路

  • C++用Dijkstra(迪杰斯特拉)算法求最短路径

    算法介绍 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低. 算法思想 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的集合(初始时只含有源点V0) (2)V-S=T:尚未确定的顶点集合 将T中顶点按递增

  • C++实现Dijkstra(迪杰斯特拉)算法

    Dijkstra算法 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,是广度优先算法的一种,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离.当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性.不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破

  • 详解Java中Dijkstra(迪杰斯特拉)算法的图解与实现

    目录 简介 工作过程 总体思路 实现 小根堆 Dijsktra 测试 简介 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边.对应问题:在无向图G=(V,E)中,假设每条边E(i)的长度W(i),求由顶点V0到各节点的最短路径. 工作过

  • java图论弗洛伊德和迪杰斯特拉算法解决最短路径问题

    目录 弗洛伊德算法 算法介绍 算法图解分析   迪杰斯特拉算法 算法介绍 算法过程  弗洛伊德算法 算法介绍 算法图解分析     第一轮循环中,以A(下标为:0)作为中间顶点 [即把作为中间顶点的所有情况都进行遍历,就会得到更新距离表和前驱关系],距离表和前驱关系更新为: 弗洛伊德算法和迪杰斯特拉算法的最大区别是: 弗洛伊德算法是从各个顶点出发,求最短路径: 迪杰斯特拉算法是从某个顶点开始,求最短路径. /** * 弗洛伊德算法 * 容易理解,容易实现 */ public void floyd

  • Python实现迪杰斯特拉算法过程解析

    一. 迪杰斯特拉算法思想 Dijkstra算法主要针对的是有向图的单元最短路径问题,且不能出现权值为负的情况!Dijkstra算法类似于贪心算法,其应用根本在于最短路径的最优子结构性质. 最短路径的最优子结构性质: 如果P(i,j)={Vi-Vk-Vs-Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径. 证明: 假设P(i,j)={Vi-Vk-Vs-Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,j)

  • Java 迪杰斯特拉算法实现查找最短距离的实现

    迪杰斯特拉算法 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.具体的计算规则我们可以通过下图进行查看. 通过这幅图我们可以简单的理解迪杰斯特拉算法算法的基础思路,下面我们就通过JAVA来实现这个算法. 算法实现 在迪杰斯特拉算法中我们需要保存从起点开始到每一个节点最短步长,这也是图中需要比较得出的步长,同时我们还

  • js图数据结构处理 迪杰斯特拉算法代码实例

    这篇文章主要介绍了js图数据结构处理 迪杰斯特拉算法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 /*//1.确定数据结构, mapf[i][j] 为点i到点j的距离 [ Infinity 2 5 Infinity Infinity Infinity Infinity 2 6 Infinity Infinity Infinity Infinity 7 1 Infinity Infinity 2 Infinity 4 Infinity

  • Python实现迪杰斯特拉算法并生成最短路径的示例代码

    def Dijkstra(network,s,d):#迪杰斯特拉算法算s-d的最短路径,并返回该路径和代价 print("Start Dijstra Path--") path=[]#s-d的最短路径 n=len(network)#邻接矩阵维度,即节点个数 fmax=999 w=[[0 for i in range(n)]for j in range(n)]#邻接矩阵转化成维度矩阵,即0→max book=[0 for i in range(n)]#是否已经是最小的标记列表 dis=[

  • C/C++最短路径算法之迪杰斯特拉Dijkstra的实现详解

    目录 前言 一.迪杰斯特拉(Dijkstra)算法是什么 二.实现步骤 1.算法思路 2.进入主函数ShortestPath() 1.创建final数组并且初始化path[].dist[]数组 2.对于节点的初始化 3.进入主循环 三.全部代码(邻接表下) 四.全部代码(邻接矩阵下) 五.测试代码(邻接表下) 总结 前言 我们在生活中常常面临对路径选择的决策问题,这就要用到最短路径的算法了. 对于我这种榆木脑袋,显然迪杰斯特拉的这种算法有点高深.主要是我笨. 对于网图来说,最短路径,就是指两个顶

  • 基于Python实现迪杰斯特拉和弗洛伊德算法

    图搜索之基于Python的迪杰斯特拉算法和弗洛伊德算法,供大家参考,具体内容如下 Djstela算法 #encoding=UTF-8 MAX=9 ''' Created on 2016年9月28日 @author: sx ''' b=999 G=[[0,1,5,b,b,b,b,b,b],\ [1,0,3,7,5,b,b,b,b],\ [5,3,0,b,1,7,b,b,b],\ [b,7,b,0,2,b,3,b,b],\ [b,5,1,2,0,3,6,9,b],\ [b,b,7,b,3,0,b,5

随机推荐