先上图:

现在要找到地点V1到其余各个地点的最短路径(图中数字的单位默认为km.)。有一个原则是:永远找最小,确保无更小。

第一步:v1->v1,v1->v2,...v1->v7的距离用一维数组dis[0],dis[1],dis[2],...dis[6]表示。初始化数组:dis=[0 50 inf inf 30 inf inf];

第二步:找到dis数组中的最小值(注意不算v1->v1=0),它是dis[4]=30;这个距离就是v1->v5的最小距离了,因为所有的距离都是正数,如果你从v1出发,通过其他顶点绕路绕到v5,那总距离肯定大于30,因为30+(一个大于0的数)肯定大于30.此时,找到了v1->v5的最短路径;

第三步:把顶点v5置为true,代表顶点v5已被访问;

第四步:看v5通往里,从图上可以看到v5通往v3和v7,v5->v3的距离是60,v5->v7的距离是120,所以通过v5中转到v3和v7后,v1->v3的距离变成30+60=90,v1->v7的距离变成30+120=150;这对dis数组中保存的v1到其它各个顶点的距离产生了影响, 此时就用更小的值去更新dis数组中的值。更新后的dis数组是:dis=[0 50 90 inf 30 inf 150].(注:inf代表无穷大)

第五步:找dis数组中除去v1->v5=30这个值之后的最小值,它是v1->v2=50,找到后把顶点v2置为ture.

第六步:从v1出发,通过v2中转,看v2会到达哪里。可以看到,v2->v3=20,这时更新dis数组中v1->v3值,把90更新成70.此时数组dis=[0 50 70 inf 30 inf 150].

第七步:重复第5步,找排除掉顶点是ture的值后,剩余的数的最小值,它是v1->v3=70,把顶点v3置为true.

第八步:从v1出发,通过v3中转,看v3会到达哪里。可以看到,v3->v7=10,这时更新dis数组中v1->v7值,把150更新成80.此时数组dis=[0 50 70 inf 30 inf 80].

第九步:结束!

最终结果:

以下C++代码来源于:https://blog.csdn.net/qq_35644234/article/details/60870719

Dijkstra.h文件的代码:

/************************************************************/
/* 程序作者:Willam */
/* 程序完成时间:2017/3/8 */
/* 有任何问题请联系:2930526477@qq.com */
/************************************************************/
//@尽量写出完美的程序 #pragma once
//#pragma once是一个比较常用的C/C++杂注,
//只要在头文件的最开始加入这条杂注,
//就能够保证头文件只被编译一次。 #include<iostream>
#include<string>
using namespace std; /*
本程序是使用Dijkstra算法实现求解最短路径的问题
采用的邻接矩阵来存储图
*/
//记录起点到每个顶点的最短路径的信息
struct Dis {
string path;
int value;
bool visit;
Dis() {
visit = false;
value = ;
path = "";
}
}; class Graph_DG {
private:
int vexnum; //图的顶点个数
int edge; //图的边数
int **arc; //邻接矩阵
Dis * dis; //记录各个顶点最短路径的信息
public:
//构造函数
Graph_DG(int vexnum, int edge);
//析构函数
~Graph_DG();
// 判断我们每次输入的的边的信息是否合法
//顶点从1开始编号
bool check_edge_value(int start, int end, int weight);
//创建图
void createGraph();
//打印邻接矩阵
void print();
//求最短路径
void Dijkstra(int begin);
//打印最短路径
void print_path(int);
};

Dijkstra.cpp文件的代码:

#include"Dijkstra.h"

//构造函数
Graph_DG::Graph_DG(int vexnum, int edge) {
//初始化顶点数和边数
this->vexnum = vexnum;//this 代表调用构造函数的那一个一个对象的地址
this->edge = edge;
//为邻接矩阵开辟空间和赋初值
arc = new int*[this->vexnum];//arc 是二级指针
dis = new Dis[this->vexnum];
for (int i = ; i < this->vexnum; i++) {
arc[i] = new int[this->vexnum];
for (int k = ; k < this->vexnum; k++) {
//邻接矩阵初始化为无穷大
arc[i][k] = INT_MAX;
}
}
}
//析构函数
Graph_DG::~Graph_DG() {
delete[] dis;
for (int i = ; i < this->vexnum; i++) {
delete this->arc[i];
}
delete arc;
} // 判断我们每次输入的的边的信息是否合法
//顶点从1开始编号
bool Graph_DG::check_edge_value(int start, int end, int weight) {
if (start< || end< || start>vexnum || end>vexnum || weight < ) {
return false;
}
return true;
} void Graph_DG::createGraph() {
cout << "请输入每条边的起点和终点(顶点编号从1开始)以及其权重" << endl;
int start;
int end;
int weight;
int count = ;
while (count != this->edge) {
cin >> start >> end >> weight;
//首先判断边的信息是否合法
while (!this->check_edge_value(start, end, weight)) {
cout << "输入的边的信息不合法,请重新输入" << endl;
cin >> start >> end >> weight;
}
//对邻接矩阵对应上的点赋值
arc[start - ][end - ] = weight;
//无向图添加上这行代码
//arc[end - 1][start - 1] = weight;
++count;
}
} void Graph_DG::print() {
cout << "图的邻接矩阵为:" << endl;
int count_row = ; //打印行的标签
int count_col = ; //打印列的标签
//开始打印
while (count_row != this->vexnum) {
count_col = ;
while (count_col != this->vexnum) {
if (arc[count_row][count_col] == INT_MAX)
cout << "∞" << " ";
else
cout << arc[count_row][count_col] << " ";
++count_col;
}
cout << endl;
++count_row;
}
}
void Graph_DG::Dijkstra(int begin){
//首先初始化我们的dis数组
int i;
for (i = ; i < this->vexnum; i++) {
//设置当前的路径
dis[i].path = "v" + to_string(begin) + "-->v" + to_string(i + );
dis[i].value = arc[begin - ][i];
}
//设置起点的到起点的路径为0
dis[begin - ].value = ;
dis[begin - ].visit = true; int count = ;
//计算剩余的顶点的最短路径(剩余this->vexnum-1个顶点)
while (count != this->vexnum) {
//temp用于保存当前dis数组中最小的那个下标
//min记录的当前的最小值
int temp = ;
int min = INT_MAX;
for (i = ; i < this->vexnum; i++) {
if (!dis[i].visit && dis[i].value<min) {
min = dis[i].value;
temp = i;
}
}
//cout << temp + 1 << " "<<min << endl;
//把temp对应的顶点加入到已经找到的最短路径的集合中
dis[temp].visit = true;
++count;
for (i = ; i < this->vexnum; i++) {
//注意这里的条件arc[temp][i]!=INT_MAX必须加,不然会出现溢出,从而造成程序异常
if (!dis[i].visit && arc[temp][i] != INT_MAX && (dis[temp].value + arc[temp][i]) < dis[i].value) {
//如果新得到的边可以影响其他为访问的顶点,那就更新它的最短路径和长度
dis[i].value = dis[temp].value + arc[temp][i];
dis[i].path = dis[temp].path + "-->v" + to_string(i + );
}
}
} }
void Graph_DG::print_path(int begin) {
string str;
str = "v" + to_string(begin);
cout << "以" << str << "为起点的图的最短路径为:" << endl;
for (int i = ; i != this->vexnum; i++) {
if (dis[i].value != INT_MAX)
cout << dis[i].path << "=" << dis[i].value << endl;
else {
cout << dis[i].path << "是无最短路径的" << endl;
}
}
}

main.cpp文件的代码:

#include"Dijkstra.h"

//检验输入边数和顶点数的值是否有效,可以自己推算为啥:
//顶点数和边数的关系是:((Vexnum*(Vexnum - 1)) / 2) < edge
bool check(int Vexnum, int edge) {
if (Vexnum <= || edge <= || ((Vexnum*(Vexnum - )) / ) < edge)
return false;
return true;
}
int main() {
int vexnum; int edge; cout << "输入图的顶点个数和边的条数:" << endl;
cin >> vexnum >> edge;
while (!check(vexnum, edge)) {
cout << "输入的数值不合法,请重新输入" << endl;
cin >> vexnum >> edge;
}
Graph_DG graph(vexnum, edge);
graph.createGraph();
graph.print();
graph.Dijkstra();
graph.print_path();
system("pause");
return ;
}

运行结果:


最短路径问题----Dijkstra算法的解释的更多相关文章

  1. 最短路径 | 深入浅出Dijkstra算法(一)

    参考网址: https://www.jianshu.com/p/8b3cdca55dc0 写在前面: 上次我们介绍了神奇的只有五行的 Floyd-Warshall 最短路算法,它可以方便的求得任意两点 ...

  2. 经典树与图论(最小生成树、哈夫曼树、最短路径问题---Dijkstra算法)

    参考网址: https://www.jianshu.com/p/cb5af6b5096d 算法导论--最小生成树 最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树. im ...

  3. 单源最短路径(dijkstra算法)php实现

    做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...

  4. 【算法设计与分析基础】25、单起点最短路径的dijkstra算法

    首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...

  5. 数据结构与算法--最短路径之Dijkstra算法

    数据结构与算法--最短路径之Dijkstra算法 加权图中,我们很可能关心这样一个问题:从一个顶点到另一个顶点成本最小的路径.比如从成都到北京,途中还有好多城市,如何规划路线,能使总路程最小:或者我们 ...

  6. 【算法导论】单源最短路径之Dijkstra算法

    Dijkstra算法解决了有向图上带正权值的单源最短路径问题,其运行时间要比Bellman-Ford算法低,但适用范围比Bellman-Ford算法窄. 迪杰斯特拉提出的按路径长度递增次序来产生源点到 ...

  7. 最短路径问题---Dijkstra算法详解

    侵删https://blog.csdn.net/qq_35644234/article/details/60870719 前言 Nobody can go back and start a new b ...

  8. 算法学习记录-图——最短路径之Dijkstra算法

    在网图中,最短路径的概论: 两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点. 维基百科上面的解释: 这个算法是通过为每个顶点 v 保留目前为止所找到的从 ...

  9. ACM: HDU 3790 最短路径问题-Dijkstra算法

    HDU 3790 最短路径问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Des ...

随机推荐

  1. useradd umask报错 root用su 切换到普通用户提示输入密码并报密码错误

    添加新用户与以下文件有关联: /etc/default/useradd [root@localhost pam.d]# cat /etc/default/useradd # useradd defau ...

  2. EVB-P6UL:一识庐山真面目

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 本文使用Markdown写成,为获得更好的阅读体验与正确的图片链接显示,请访问我的博客原文: 在爱板网上看到这个活动,昨晚确认,今 ...

  3. js:Razor视图下服务器代码给Javascript变量赋值

    namespace Razor.Controllers { public class JSController : Controller { public ActionResult Index() { ...

  4. JavaScript-4.1-简单的表单操作,函数用法---ShinePans

    <html> <head> <meta http-equiv="content-type" content="text/html;chars ...

  5. Lua学习四----------Lua变量

    © 版权声明:本文为博主原创文章,转载请注明出处 1.Lua变量 - 变量在使用前,必须在代码中进行声明,即创建该变量 - 编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值 ...

  6. neural network and deep learning笔记(1)

    neural network and deep learning 这本书看了陆陆续续看了好几遍了,但每次都会有不一样的收获. DL领域的paper日新月异.每天都会有非常多新的idea出来,我想.深入 ...

  7. servletResponse outputStream输出数据

    package response; import java.io.IOException;import java.io.OutputStream; import javax.servlet.Servl ...

  8. 【Python基础】之异常

    一.常见异常 try: open('abc.txt','r') except FileNotFoundError: print('异常啦!') 输出结果: ======= 异常啦! 我们通过 open ...

  9. erlang的timer定时器浅析

    timer作为其计时器: erlang的计时器timer是通过一个唯一的timer进程实现的,该进程是一个gen_server,用户通过timer:send_after和timer:apply_aft ...

  10. 用Newtonsoft将json串转为对象的方法(详解)

    首先,将json串转为一个JObject对象: JObject jo = (JObject)JsonConvert.DeserializeObject(CurrentSelectedItemReq) ...