个人整理,原创发布,转载请标注博客来源。https://editor.csdn.net/md/?articleId=102799813
很多时候,总会忽略了一些你认为不需要的知识体系,但最终你发现,你又要花大量的时间去弥补这个空缺。


算法简介
狄克斯特拉算法,用于计算出在非负权重的情况下,图中起点到终点的最短路径......
解决问题
  1. 从A出发是否存在到达B的路径;
  2. 从A出发到达B点的最短路径(时间最少或者路径最少);
算法思路
  1. 找出“最便宜”的节点,即可在最短时间内到达的节点;
  2. 更新此节点到“邻居”节点的开销,其含义下文案例说明。
  3. 重复上述过程,直到对图中的所有节点都这样做了;
  4. 计算最短路径;
案例分析
  • 案例一

    图示(MarkDown画的图)

6
2
1
5
3
起点
A
B
终点
  1. 首先列出起点到各相连节点的耗费时间

    父节点 节点 耗时
    起点 A 6分钟
    起点 B 2分钟
    终点 ∞ 无穷大
  2. 获取耗时最短的节点,由上表可以看出是起点->B节点花费时间最少,计算节点B前往各个邻居节点的所需时间,并更新原本需要花费更多的时间的节点:

    父节点 节点 耗时
    B A 5分钟 (更新耗时)
    起点 B 2分钟
    B 终点 7 (更新耗时)
  3. 此时,B节点添加进已处理的列表中,不再进行处理,现在只剩余A节点到各邻居节点的所需要的耗时,并更新原本需要花费更多的时间的节点。

    父节点 节点 耗时
    B A 5分钟
    起点 B 2分钟
    A 终点 6 (更新耗时)
  4. 有表格可以看出,最终路径是起点-> B -> A -> 终点,耗时6分钟。

算法编码
/** Dijkstra.cpp**  Created on: Oct 21, 2019*      Author: kjh*/#include <map>
#include <set>
#include <string>
#include <vector>
#include <iostream>
#include <limits>using std::map;
using std::string;
using std::set;class Dijkstra {public:typedef std::map<std::string, int> KeyValueNode;typedef std::map<std::string, KeyValueNode> GraphMap;void init();void process(const std::string& startKey, const std::string& target);private:std::string getMinCost(KeyValueNode& keyVals);void process_node(const std::string& key, KeyValueNode& keyVals);void print(const std::string& target);private:// for graph.GraphMap _map;// for visited nodestd::set<string> _visited_set;// for parents relationstd::map<string, string> _node_parents;// 存放到各节点需要的最小时间KeyValueNode _cost_path;
};/******************************** start -->  A (6)*       -->  B (2)*       B -->  A  (3)*         -->  fin(5)*            A --> fin (1)******************************/
void Dijkstra::init() {_map.clear();_visited_set.clear();_cost_path.clear();_node_parents.clear();// init graphKeyValueNode start = {{"A", 6}, {"B", 2}};KeyValueNode b = {{"A", 3}, {"FIN", 5}};KeyValueNode a = {{"FIN", 1}};_map = {{"START", start}, {"B", b}, {"A", a}};
}std::string Dijkstra::getMinCost(KeyValueNode& keyVals) {int min_cost = std::numeric_limits<int>::max();string min_key;for (auto& it : keyVals) {if (it.second < min_cost && _visited_set.count(it.first) != 1) {min_cost = it.second;min_key = it.first;}}return min_key;
}void Dijkstra::process(const std::string& startKey, const std::string& target) {// find start key.auto iter = _map.find(startKey);if (iter == _map.end()) {return ;}// 处理起点的邻居节点,讲邻居节点的耗时加入cost_path.for (auto & node :iter->second) {int cost = node.second;_cost_path.insert(node);_node_parents.insert(std::make_pair(node.first, startKey));}// 查找cost最小的节点std::string mini_key = getMinCost(_cost_path);while(!mini_key.empty()) {std::cout << "process node: " << mini_key << std::endl;auto it = _map.find(mini_key);if (it == _map.end()) {break;}// 处理cost最小节点邻居节点,并更新cost_pathprocess_node(mini_key, it->second);_visited_set.insert(mini_key);mini_key = getMinCost(_cost_path);}// 输出结果print(target);
}void Dijkstra::process_node(const std::string& key, KeyValueNode& keyVals) {auto it = _cost_path.find(key);if (it == _cost_path.end()) {return;}int has_cost = it->second;for (auto& node : keyVals) {int cost = node.second;cost = has_cost + cost;auto cit = _cost_path.find(node.first);if (cit == _cost_path.end()) {_cost_path.insert(std::make_pair(node.first, cost));_node_parents.insert(std::make_pair(node.first, key));} else {int old_cost = cit->second;if (cost < old_cost) {_cost_path.erase(cit);_cost_path.insert(std::make_pair(node.first, cost));_node_parents.erase(node.first);_node_parents.insert(std::make_pair(node.first, key));}}}
}void Dijkstra::print(const std::string& target) {auto citer = _node_parents.find(target);if (citer != _node_parents.end()) {std::vector<std::string> path;std::string parents = citer->second;path.push_back(target);while(!parents.empty()) {path.push_back(parents);auto piter = _node_parents.find(parents);if (piter != _node_parents.end()) {parents = piter->second;} else {parents = "";}}int size = path.size();std::cout << "Path : ";for (int i = size -1 ; i >= 0; i--) {std::cout << path[i];if (i > 0) {std::cout << " --> ";}}auto cost_iter = _cost_path.find(target);if (cost_iter != _cost_path.end()) {std::cout << " cost: " << cost_iter->second;}std::cout << std::endl;} else {std::cout << "Does not exists to " << target << " path" << std::endl;}
}int main() {Dijkstra test;test.init();test.process("A", "H");return 0;
}// g++ Dijkstra.cpp -std=c++11
  • 案例二

    案例一中选择了最简单的图,案例二将图复杂一步,来说明算法的思想

5
1
10
5
3
3
6
2
10
A
B
C
E
D
H
F
G
  • 如果使用广度优先算法,可以得出A到H的最短路径为:A–>B–>E–>H
  • 图中给每个节点赋予权重值,就可以使用狄克斯特拉算法来求解A到H的权重和值最小的路径。

按照案例一中的步骤,进行分析:

  1. 取A(起点)到各节点的耗时
父节点 节点 耗时
A       |    B      |   5
A       |    C      |   1
A       |    H      |   +∝
  1. 找出A节点到达各邻居节点中权重最小的节点,此时C节点的权重最小,将C节点邻居节点D、F加入节点图表中
父节点 节点 耗时 标志
A       |    B      |   5       |
A       |    C      |   1       |   C已处理
A       |    H      |   +∝     |
C       |    D      |   6       |
C       |    F      |   7       |
  1. 在加入C节点的邻居节点后,从最新的列表中找出A到各节点最小权重点,此时B最小;处理B节点的各邻居节点
父节点 节点 耗时 标志
A       |    B      |   5       |   B已处理
A       |    C      |   1       |   C已处理
A       |    H      |   +∝     |
C       |    D      |   6       |
C       |    F      |   7       |
B       |    E      |   15      |
  1. A的相邻节点已经处理完成,此时找最小权重路径,C-D,计算处理相邻节点的耗时,并标记D已处理
父节点 节点 耗时 标志
A       |    B      |   5       |   B已处理
A       |    C      |   1       |   C已处理
A       |    H      |   +∝     |
C       |    D      |   6       |   D已处理
C       |    F      |   7       |
D       |    E      |   9       |
  1. 同理处理F
父节点 节点 耗时 标志
A       |    B      |   5       |   B已处理
A       |    C      |   1       |   C已处理
E       |    H      |   +∝     |
C       |    D      |   6       |   D已处理
C       |    F      |   7       |   F已处理
D       |    E      |   9       |
F       |    G      |   9       |
  1. 同理处理E
父节点 节点 耗时 标志
A       |    B      |   5       |   B已处理
A       |    C      |   1       |   C已处理
E       |    H      |   12      |
C       |    D      |   6       |   D已处理
C       |    F      |   7       |   F已处理
D       |    E      |   9       |   E已处理
F       |    G      |   9       |
  1. 同理更新G
父节点 节点 耗时 标志
A       |    B      |   5       |   B已处理
A       |    C      |   1       |   C已处理
E       |    H      |   12      |
C       |    D      |   6       |   D已处理
C       |    F      |   7       |   F已处理
D       |    E      |   9       |   E已处理
F       |    G      |   9       |   G已处理

经过上述的过程推敲,可以看出,最后一步处理G,其用时没有比之前更小了,固不更新列表值。
有次的出最小权重:12, 路径:A–>C–>D–>E–>H

程序验证:
// 替换案例一中初始化函数,生成新的图void Dijkstra::init() {_map.clear();_visited_set.clear();_cost_path.clear();_node_parents.clear();// init graphKeyValueNode a = {{"B", 5}, {"C", 1}};KeyValueNode b = {{"E", 10}};KeyValueNode c = {{"D", 5}, {"F", 6}};KeyValueNode d = {{"E", 3}};KeyValueNode e = {{"H", 3}};KeyValueNode f = {{"G", 2}};KeyValueNode g = {{"H", 10}};_map = {{"A", a}, {"B", b}, {"C", c}, {"D", d}, {"E", e}, {"F", f}, {"G", g}};
}
  • 从案例的图示做为输入编写了算法,即在固定的图规格中寻找消耗最小的路径。
  • 转化到工程项目中,可能给出的图会很复杂,需要根据实际的工程问题来解答(狄克斯特拉算法的核心不会变化,我们就需要从具体的问题抽象划分图解)。
  • 比如将复杂的问题分解成我们需要的两点间的图。在应用狄克斯特拉算法来解决。
  • 上述只是一个解题的思路,具体问题还需要具体对待。

狄克斯特拉算法 - 学习整理相关推荐

  1. 《算法图解》学习笔记(七):狄克斯特拉算法(附代码)

    欢迎关注WX公众号:[程序员管小亮] python学习之路 - 从入门到精通到大师 文章目录 欢迎关注WX公众号:[程序员管小亮] [python学习之路 - 从入门到精通到大师](https://b ...

  2. 【学习 记录】狄克斯特拉算法 - Java

    最近学习<算法图解>一书时,看到狄克斯特拉算法之前没有使用过,在学习后用常用语言Java将算法实现出来以加深印象. 作用 狄克斯特拉算法用于找出最快的路径,而常用的广度优先搜索算法可用于找 ...

  3. 图解算法学习笔记(七):狄克斯特拉算法

    目录 1)使用狄克斯特拉算法 2)术语 3)实现 4)小结 本章内容; 介绍加权图,提高或降低某些边的权重: 介绍狄克斯特拉算法,找出加权图中前往X的最短路径: 介绍图中的环,它导致狄克斯特拉算法不管 ...

  4. 算法学习之狄克斯特拉算法

    加权图 在了解狄克斯特拉算法之前,先介绍一下加权图. 如图,假设你要从起点出发到达终点,如果只考虑换乘少,即最短路径.那么可以使用广度优先搜索算法,该算法我之前简单的写过,链接点这里.但是,现在你要找 ...

  5. 小白的算法初识课堂(part7)--狄克斯特拉算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 狄克斯特拉算法 具体步骤实现 术语 跳蚤市场 具体步骤实现 负权边 python实现 狄克斯特拉算法 在上一个 ...

  6. 初学狄克斯特拉算法~(待提高)

    读书笔记 狄克斯特拉算用来寻找加权图的"最短路径"(不一定是段数最少,我们需要一定的量度,比如说最少花费,最短时间等,bfs只是解决了段数的最短路径问题) 鉴于无向图就是一个环,而 ...

  7. 算法图解part7:狄克斯特拉算法

    算法图解part7:狄克斯特拉(Dijkstra)算法 1.狄克斯特拉算法(Dijkstra's algorithm) 2.术语 3.负权边 4.实现狄克斯特拉算法 4.1 最短路径思路 4.2 py ...

  8. 狄克斯特拉算法(入门)

    狄克斯特拉算法可以找出加权图中前往X的最短路径. 注意: - 其只适用于有向无环图 - 适用于正权边,负权边的将出错(贝尔曼-福德算法适用于负权边) 步骤: 找出当前最"便宜"的节 ...

  9. 算法(四):图解狄克斯特拉算法

    算法简介 狄克斯特拉算法(Dijkstra )用于计算出不存在非负权重的情况下,起点到各个节点的最短距离 可用于解决2类问题: 从A出发是否存在到达B的路径: 从A出发到达B的最短路径(时间最少.或者 ...

最新文章

  1. 敏捷研发落地之持续集成
  2. C#之windows桌面软件第九课:汉字串口助手
  3. linux的strace命令(详解)
  4. endnotex8与9的区别_下载安装EndnoteX8或EndnoteX9,建立数据库并以自己的名字命名。...
  5. 计算机程序停止工作怎么办,如何将“某某程序已正常停止工作,请关闭程序”这个提示自动关闭...
  6. 24V电压TVS二极管选型
  7. 利用C语言编程输出小写英文字母表的大写形式(以5为间隔)
  8. 未能解决并且期待解决的第二个诡异事件----HashMap相关方法
  9. SAP——ABAP报表的一般格式
  10. 方舟非专用服务器稳定吗,方舟非专用服务器
  11. OSChina 周二乱弹 —— 春节假期已经完全结束
  12. 网页设计(三)——JavaScript
  13. Alpine执行bash
  14. 图论(图、树基本知识)
  15. Proteus + μVision Keil单片机仿真教程(一)点亮一个LED
  16. 电子白板软件使用详解
  17. Verdi -- 保存调试的所有设置和界面
  18. webflux - 统一响应 ModifyResponseBodyGatewayFilterFactory
  19. office共享——多人编辑
  20. 沈阳航空航天大学计算机考研真题文件模板

热门文章

  1. 网上二手服务器能做家用电脑吗?
  2. Android 按电源键亮屏/息屏流程分析
  3. win10用户名改了以后,C盘中用户文件夹下的以用户名命名的文件夹名字没有变化?还是之前的用户
  4. 微信的服务器域名地址,微信服务器域名设置
  5. 公司有打算使用神州数码的EasyFlow工作流管理系统
  6. 什么是软链接, 什么是硬链接
  7. 【洛谷】P5149 会议座位
  8. iOS程序员面试笔试宝典整理
  9. 安卓手机拨号键盘隐藏工程代码大全
  10. php二码合一,PS4slim二码合一怎么看