C++迪杰斯特拉算法求最短路径
一:算法历史
迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
二:算法思想
按路径长度递增次序产生算法:
把顶点集合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 = ; 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] = -;//如果v0和v之间无边,则将v的前驱初始化为-1
}
S[v0] = true; //将v0加入s
D[v0] = ;//源点到源点的权值为0
//---------初始化结束,开始主循环,每次求得v0到某个顶点的最短路径,将v加到S数组
for (int i = ; i < n; i++)//依次对其余n-1个顶点进行计算
{
int min = MAX;
int v = v0;
for (int w = ; w < n; w++)
{
if (!S[w] && D[w] < min)
{//选择一条当前最短路径,终点为v
v = w;
min = D[w];
}
S[v] = true;//将v加到s集合中
for (int w = ; 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,,MAX,,,MAX,, },
{MAX,MAX,MAX,MAX,,,MAX,,MAX,MAX },
{MAX,MAX,MAX,,MAX,MAX,,MAX,MAX,MAX },
{,MAX,,MAX,MAX,MAX,MAX,MAX,,MAX },
{MAX,,MAX,MAX,MAX,,MAX,MAX,MAX,MAX },
{,,MAX,MAX,,MAX,MAX,,MAX, },
{,MAX,,MAX,MAX,MAX,MAX,MAX,MAX,MAX },
{MAX,,MAX,MAX,MAX,,MAX,MAX,MAX,MAX },
{,MAX,MAX,,MAX,MAX,MAX,MAX,MAX,MAX },
{,MAX,MAX,MAX,MAX,,MAX,MAX,MAX,MAX }
},,};
int f, ff;
int start, end;
while (true)
{
cout << endl;
menu();
cin >> f;
if (f == )
{
jmenu();
cin >> ff;
//景点信息从文件中读取
ifstream outfile("schooltravel.txt", ios :: out | ios :: binary);
if (!outfile)
{
cerr << "读取景点介绍文件失败!" << endl;
exit(1);
}
string str[max];
int i = ;
while (getline(outfile, str[i++]));
cout << "|-----------------------景点介绍-------------------| " << endl;
if (ff == )
cout << str[] << endl;
else if (ff == )
cout << str[] << endl;
else if (ff == )
cout << str[] << endl;
else if(ff == )
cout << str[] << endl;
else if (ff == )
cout << str[] << endl;
else if (ff == )
cout << str[] << endl;
else if (ff == )
cout << str[] << endl;
else if (ff == )
cout << str[] << endl;
else if (ff == )
cout << str[] << endl;
else if (ff == )
cout << str[] << endl;
cout << "|-------------------------------------------------|" << endl;
}
else if (f == )
{
pmenu();
cin >> start >> end;
ShortestPath_DIJ(amg, start - );
int temp = end-;
int temp1, temp2;
int flag[max], m = ;
cout << "从" << amg.vexs[start - ] << "到" << amg.vexs[end - ] << "最短路径为:" ;
while (temp!= -)
{
flag[m++] = temp;
temp1 = temp ;
temp2 = Path[temp1];
temp = temp2;
}
for (int i = m-; i >= ; i--)
{
cout <<amg.vexs[flag[i]] << "->";
}
cout << endl;
cout << "最短路径值为:" << D[end - ] <<"米"<< endl;
}
else if (f == )
{
backGround();
}
else if (f == )
{
cout << ">>>退出成功!" << endl;
exit();
}
}
}
(4)运行截图:
schooltravel.txt下载地址:https://files.cnblogs.com/files/dmego/schooltravel.rar
C++迪杰斯特拉算法求最短路径的更多相关文章
- js迪杰斯特拉算法求最短路径
1.后台生成矩阵 名词解释和下图参考:https://blog.csdn.net/csdnxcn/article/details/80057574 double[,] arr = new double ...
- 算法与数据结构(六) 迪杰斯特拉算法的最短路径(Swift版)
上篇博客我们详细的介绍了两种经典的最小生成树的算法,本篇博客我们就来详细的讲一下最短路径的经典算法----迪杰斯特拉算法.首先我们先聊一下什么是最短路径,这个还是比较好理解的.比如我要从北京到济南,而 ...
- Dijkstra(迪杰斯特拉)算法求解最短路径
过程 首先需要记录每个点到原点的距离,这个距离会在每一轮遍历的过程中刷新.每一个节点到原点的最短路径是其上一个节点(前驱节点)到原点的最短路径加上前驱节点到该节点的距离.以这个原则,经过N轮计算就能得 ...
- 图->最短路径->单源最短路径(迪杰斯特拉算法Dijkstra)
文字描述 引言:如下图一个交通系统,从A城到B城,有些旅客可能关心途中中转次数最少的路线,有些旅客更关心的是节省交通费用,而对于司机,里程和速度则是更感兴趣的信息.上面这些问题,都可以转化为求图中,两 ...
- 迪杰斯特拉算法dijkstra(可打印最短路径)
#include <iostream> #include <iomanip> #include <string> using namespace std; #def ...
- 最短路径之迪杰斯特拉算法的Java实现
Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是“贪心算法”的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知识准备 ...
- 图(最短路径算法————迪杰斯特拉算法和弗洛伊德算法).RP
文转:http://blog.csdn.net/zxq2574043697/article/details/9451887 一: 最短路径算法 1. 迪杰斯特拉算法 2. 弗洛伊德算法 二: 1. 迪 ...
- c语言实现迪杰斯特拉算法(邻接表)
储存结构,结构体的定义:(权值w用于表示两点间路径的花费) typedef int Status; typedef struct ENode//图的邻接表定义 { int adjVex;//任意顶点u ...
- 单源最短路径算法——Dijkstra算法(迪杰斯特拉算法)
一 综述 Dijkstra算法(迪杰斯特拉算法)主要是用于求解有向图中单源最短路径问题.其本质是基于贪心策略的(具体见下文).其基本原理如下: (1)初始化:集合vertex_set初始为{sourc ...
随机推荐
- Latex中画出函数文件的调用关系拓扑图
流程图,思维导图,拓扑图通常能把我们遇到的一些复杂的关系结构用图形的方式展现出来.在Latex中要想画这样的拓扑图,有一个很好用的绘图工具包 pgf/tikz . 1.pgf/tikz的安装:pgf/ ...
- ubuntu14.04下直接修改apache2默认目录导致wordpress样式改变的解决办法
一开始看到网上有各种各样的解决方法: 第一种是直接将 sites-available目录下的000-default.conf中的下列代码: DocumentRoot /var/www/html 修改为 ...
- winserver 08 64位安装sql05 64位提示asp版本注册
将打开 安装IIS 6.0的就可以了,然后重启下
- [Android Pro] AsyncTaskLoader vs AsyncTask
reference to : http://blog.csdn.net/a910626/article/details/45599133 我看了一下asyncTask是从LV3开始,AsyncTask ...
- adb 的使用
打出log:adb logcat -s fliterName ps:(fliterName就是你的tag)
- C# 小知识
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.C ...
- 什么是BOM头,BOM头有什么影响,怎么去掉BOM头
什么是bom头? 在utf-8编码文件中BOM在文件头部,占用三个字节,用来标示该文件属于utf-8编码,现在已经有很多软件识别bom头,但是还有些不能识别bom头,比如PHP就不能识别bom头,这也 ...
- Linux系统性能优化思路和方法
#影响Linux性能的CPU.内存.磁盘.网络等因素分析1.系统硬件资源:CPU,多核与超线程消耗CPU的业务:动态WEB服务,Mail服务器2.内存:物理内存与swap的取舍,64操作系统消耗内存的 ...
- CozyRSS开发记录-中断
接下来会对CozyRSS做一堆的修改,包括界面和功能.因为比较杂乱,而且大多是体力活,所以就不记录了.等下次再发的时候,见到的就是一个有可用性的CozyRSS了!
- [leetcode] 提醒整理之进制
12. Integer to Roman Given an integer, convert it to a roman numeral. Input is guaranteed to be with ...