引言:
来考虑一个问题,
平面上6个点,A,B,C,D,E,F,假定已知其中一些点之间的距离,
现在,要求A到其它5个点,B,C,D,E,F各点的最短距离。

如下图所示:

经过上图,我们可以轻而易举的得到A->B,C,D,E,F各点的最短距离:

目的 路径 最短距离
A=>A, A->A 0
A=>B, A->C->B 3+2=5
A=>C, A->C 3
A=>D, A->C->D 3+3=6
A=>E, A->C->E 3+4=7
A=>F, A->C->D->F 3+3+3=9

我想,如果是单单出上述一道填空题,要你答出A->B,C,D,E,F各点的最短距离,

一个小学生,掰掰手指,也能在几分钟之内,填写出来。

我们的问题,当然不是这么简单,上述只是一个具体化的例子而已。

实际上,很多的问题,如求图的最短路径问题,就要用到上述方法,不断比较、不断寻找,以期找到最短距离的路径,此类问题,便是Dijkstra 算法的应用了。当然,还有BFS算法,以及更高效的A*搜寻算法。

A*搜寻算法已在本BLOG内有所详细的介绍,本文咱们结合fibonacci堆实现Dijkstra 算法。

即,Dijkstra + fibonacci堆 c实现。

我想了下,把一个算法研究够透彻之后,还要编写代码去实现它,才叫真正掌握了一个算法。本BLOG内经典算法研究系列,已经写了18篇文章,十一个算法,所以,还有10多个算法,待我去实现。

代码风格
实现一个算法,首先要了解此算法的原理,了解此算法的原理之后,便是写代码实现。
在打开编译器之前,我先到网上搜索了一下“Dijkstra 算法+fibonacci堆实现”。

发现:网上竟没有过 Dijkstra + fibonacci堆实现的c代码,而且如果是以下几类的代码,我是直接跳过不看的:

1、没有注释(看不懂)。
2、没有排版(不舒服)。
3、冗余繁杂(看着烦躁)。

fibonacci堆实现Dijkstra 算法

ok,闲话少说,咱们切入正题。下面,咱们来一步一步利用fibonacci堆实现Dijkstra 算法吧。

前面说了,要实现一个算法,首先得明确其算法原理及思想,而要理解一个算法的原理,又得知道发明此算法的目的是什么,即,此算法是用来干什么的?

由前面的例子,我们可以总结出:Dijkstra 算法是为了解决一个点到其它点最短距离的问题。

我们总是要找源点到各个目标点的最短距离,在寻路过程中,如果新发现了一个新的点,发现当源点到达前一个目的点路径通过新发现的点时,路径可以缩短,那么我们就必须及时更新此最短距离。

ok,举个例子:如我们最初找到一条路径,A->B,这条路径的最短距离为6,后来找到了C点,发现若A->C->B点路径时,A->B的最短距离为5,小于之前找到的最短距离6,所以,便得此更新A到B的最短距离:为5,最短路径为A->C->B.好的,明白了此算法是干什么的,那么咱们先用伪代码尝试写一下吧(有的人可能会说,不是吧,我现在,什么都还没搞懂,就要我写代码了。额,你手头不是有资料么,如果全部所有的工作,都要自己来做的话,那就是一个浩大的工程了。:D。)。咱们先从算法导论上,找来Dijkstra 算法的伪代码如下:

DIJKSTRA(G, w, s)
1 INITIALIZE-SINGLE-SOURCE(G, s) //1、初始化结点工作
2 S ←
3 Q ← V[G] //2、插入结点操作
4 while Q ≠
5 do u ← EXTRACT-MIN(Q) //3、从最小队列中,抽取最小点工作
6 S ← S ∪{u}
7 for each vertex v ∈ Adj[u]
8 do RELAX(u, v, w) //4、松弛操作。

伪代码毕竟与能在机子上编译运行的代码,还有很多工作要做。

首先,咱们看一下上述伪代码,可以看出,基本上,此Dijkstra 算法主要分为以下四个步骤:

1、初始化结点工作
2、插入结点操作
3、从最小队列中,抽取最小点工作
4、松弛操作。

ok,由于第2个操作涉及到斐波那契堆,比较复杂一点,咱们先来具体分析第1、2、4个操作:

1、得用O(V)的时间,来对最短路径的估计,和对前驱进行初始化工作。

INITIALIZE-SINGLE-SOURCE(G, s)
1 for each vertex v ∈ V[G]
2 do d[v] ← ∞
3 π[v] ← NIL //O(V)
4 d[s] 0

我们根据上述伪代码,不难写出以下的代码:

void init_single_source(Graph *G,int s)
{
for (int i=0;in;i++) {
d[i]=INF;
pre[i]=-1;
}
d[s]=0;
}

2、插入结点到队列的操作

2 S ←
3 Q ← V[G] //2、插入结点操作

代码:
for (i=0;in;i++)
S[i]=0;

4、松弛操作。
首先得理解什么是松弛操作:
Dijkstra 算法使用了松弛技术,对每个顶点v<-V,都设置一个属性d[v],用来描述从源点s到v的最短路径上权值的上界,称为最短路径的估计。
RELAX(u, v, w)
1 if d[v] > d[u] + w(u, v)
2 then d[v] ← d[u] + w(u, v)
3 π[v] ← u //O(E)

同样,我们不难写出下述代码:
void relax(int u,int v,Graph *G)
{
if (d[v]>d[u]+G->w[u][v])
{
d[v] = d[u]+G->w[u][v]; //更新此最短距离
pre[v]=u; //u为v的父结点
}
}

再解释一下上述relax的代码,其中u为v的父母结点,当发现其父结点d[u]加上经过路径的距离G->w[u][v],小于子结点到源点的距离d[v],便得更新此最短距离。
请注意,说的明白点:就是本来最初A到B的路径为A->B,现在发现,当A经过C到达B时,此路径距离比A->B更短,当然,便得更新此A到B的最短路径了,即是:A->C->B,C 即成为了B的父结点(如此解释,我相信您已经明朗。:D。)。
即A=>B <== A->C->B,执行赋值操作。ok,第1、2、4个操作步骤,咱们都已经写代码实现了,那么,接下来,咱们来编写第3个操作的代码:3、从最小队列中,抽取最小点工作。相信,你已经看出来了,我们需要构造一个最小优先队列,那用什么来构造最小优先队列列?对了,堆。什么堆最好,效率最高,呵呵,就是本文要实现的fibonacci堆。为什么?ok,请看最小优先队列的三种实现方法比较:EXTRACT-MIN + RELAX

I、 简单方式: O(VV + E1)
II、 二叉/项堆: O(VlgV + |E|lgV)
源点可达:O(ElgV)
稀疏图时,有E=o(V^2/lgV),
=> O(V^2)
III、斐波那契堆:O(VlgV + E)

其中,V为顶点,E为边。好的,这样我们就知道了:Dijkstra 算法中,当用斐波纳契堆作优先队列时,算法时间复杂度为O(V*lgV + E)。额,那么接下来,咱们要做的是什么列?当然是要实现一个fibonacci堆了。可要怎么实现它,才能用到我们

Dijkstra 算法中列?对了,写成一个库的形式。库?呵呵,是一个类。

    ok,以下就是这个fibonacci堆的实现:


```c
//FibonacciHeap.h
#ifndef _FIBONACCI_HEAP_H_INCLUDED_
#define _FIBONACCI_HEAP_H_INCLUDED_  #include <functional>
#include <algorithm>  template<typename T>
struct Fib_node
{  Fib_node* ns_; //后驱结点  Fib_node *pt_; //父母结点  Fib_node* ps_; //前驱结点  Fib_node* fc_; //头结点  int rank_;     //孩子结点  bool marked_;  //孩子结点是否删除的标记  T* pv_;  Fib_node(T* pv = 0) : pv_(pv) { }  T& value(void) { return *pv_; }  void set_src(T* pv) { pv_ = pv; }
}; //Fib_node的数据结构  template<class Node, class OD>
Node* merge_tree(Node*a, Node* b, OD small)  //合并结点
{


[转载于以下网址](https://blog.csdn.net/a_big_pig/article/details/44163903)

Dijkstra 算法+fibonacci堆的逐步c实现相关推荐

  1. dijkstra算法及其堆优化

    dijkstra算法及其堆优化 (个人笔记写给自己看的) 数据结构:链式前向星,优先队列 dijkstra算法: vis数组初始化为0,dis数组初始化为inf(很大的值如:0x7fffffff),设 ...

  2. Dijkstra算法和堆优化

    目录 Dijkstra介绍 算法思想 具体步骤 代码实现 Dijkstra链式向前星 优化思路 实现步骤 代码实现 Dijkstra链式向前星堆优化 优化思路 优化步骤 代码实现 参考资料(帮助理解代 ...

  3. Dijkstra算法及堆优化

    1.有向无环图的单源点最短路 其实跟之前说的最长路是一样的 思路:广搜(拓扑排序)+ DP 如下图所示: 2.一般图的单源点最短路 Dijkstra(迪杰斯特拉)算法 算法思路:每次找离起点最近的那个 ...

  4. Dijkstra算法(堆优化版求稀疏图最短路)

    南昌理工acm集训队 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959年提出的,是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题. 基本思想 Dijkstra算法是用来解决不 ...

  5. 第六天PAT-A1003 Emergency最短路问题Dijkstra算法(小根堆)描述及模板

    A1003 Description: 作为一个城市的急救队领导,你会得到你所在城市的一个特别地图.这张地图展示了一些由一些路径相连的几个零散的城市.每个城市的救援队总数和连接两个城市的道路的长度都标注 ...

  6. DijKstra算法普通+堆优化链式向前星

    朴素版本 #include<bits/stdc++.h> using namespace std; const int maxn = 10010; const int inf = 0x3f ...

  7. 朴素版Dijkstra算法

    文章目录 一.Dijkstra是什么? 二.使用步骤 1.Dijkstra的基本原理 2.时间复杂度 三.代码实现思路 四.代码实现 总结 一.Dijkstra是什么? Dijkstra算法是由荷兰计 ...

  8. 03 最短路 dijkstra算法spfa算法floyd算法(附带实例代码) 图论-1

    文章目录 最短路 邻接表的图如下 邻接矩阵如下图 链表实现邻接表实现代码 单源最短路径 Dijkstra 算法 朴素版本 Dijkstra 实现代码 堆优化的dijkstra算法代码实现 Bellma ...

  9. Dijkstra算法详解

    什么是Dijkstra算法 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又 叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最 短 ...

  10. Dijkstra算法求最短路

    一.算法描述 Dijkstra算法的流程如下: 1.初始化dist[1] = 0,其余节点的dist值为无穷大. 2.找出一个未被标记的.dist[x]最小的节点x,然后标记节点x. 3.扫描节点x的 ...

最新文章

  1. 执行eclipse,迅速failed to create the java virtual machine。
  2. JavaWeb(七)——Cookie、Session
  3. [Swift]最强UIButton解析 | #selector()绑定点击事件
  4. vue 开发环境搭建
  5. android 按键上浮动画_android – 浮动动作按钮动画
  6. HTML5 API详解(7):link prefetch提升加载速度,优化体验
  7. 蚂蚁森林:不存在网友反馈的“没有造林”的情况 干旱造成梭梭矮小
  8. CSS实现兼容性的渐变背景(gradient)效果(转)
  9. 在Winform开发框架中实现对数据库的加密支持(转)
  10. 【2019 BAPC - D】Deck Randomisation【中国剩余定理 + 循环节】
  11. 防止各大网盘下载限速解决方案--idman
  12. sata接口 图解 定义_SATA定义及接口
  13. 新版gsp计算机系统全套资料,新版GSP对计算机系统的需求表
  14. chrome谷歌浏览器离线安装axure插件打开页面原型
  15. 初学者想自学单片机需要买什么呢?
  16. (Tekla Structures二次开发)使用VS创建Tekla Structures插件的模板
  17. 小飞鱼通达二开 通过开发工作流接口集成ERP系统(图文)
  18. 第7章第29节:四图排版:四张图片并列排版 [PowerPoint精美幻灯片实战教程]
  19. asterisk拨号规则(包含匹配规则说明)转
  20. js数据类型强制转换--转换为String

热门文章

  1. 虚幻airsim1:下载安装
  2. [work*] 贝叶斯公式的通俗解释
  3. AI 人工智能学习之需要具备的基础知识
  4. Ubuntu搭建FTP服务器
  5. HTML标记大全参考手册
  6. 微信公众号后台接口文档
  7. 矩阵按键原理和BUG
  8. BT.2020 新一代超高清UHD视频制作与显示系统标准
  9. 0.96寸OLED屏幕控制器SSD1306详解
  10. c代码实现matlab中对矩阵fftshift思路