Dijkstra算法

1.定义概览

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,

在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)

2.算法描述

首先把起点到所有点的路径花费都设为无穷大(起点到起点的花费设为0),对于一个没有被标记过的且在没有标记过的点中从起点到这个点的花费最小(最开始一定是起点)点v,设起点到这个点的花费为v.dist, 如果点v到与它相邻的点w满足v.dist + <v,w>.weight < w.dist,其中<v,w>.weight表示从v到w的权值,那么就令w.dist = v.dist + <v,w>.weight ,并把节点v标记(不要标记w),重复以上步骤,直到所有点被标记,所有点的i.dist就是起点到这个点所要的最小花费。

3 代码实现

按照上述思想,实现代码即可,图用邻接表表示。

#include <iostream>
using namespace std; #define Inf 65535
#define NotAVerter -1 /////////////////////邻接表的相关定义//////////////////////
typedef struct EdgeNode *position;
typedef struct Led_table* Table; struct EdgeNode //边表结点
{
int adjvex; // 邻接点域,存储该顶点对应的下标
int weight; // 对应边的权值
position next; // 链域,指向下一个邻接点
}; struct Led_table // 邻接表结构
{
int data; //邻接表的大小
position *firstedge; //边表头指针,可以理解为数组
}; //////////////////////////邻接表相关函数定义///////////////
Table Creat_Lable (int MaxElements) //MaxElements参数为希望创建的节点数
{ Table table1 = static_cast<Table> (malloc(sizeof(struct Led_table)));
table1->data = MaxElements;
if (table1 == NULL)
{
cout << "out of space!!!";
} table1->firstedge = static_cast<position*>(malloc(sizeof(position)*(table1->data)));
if (table1->firstedge == NULL)
{
cout << "out of space!!!";
} //给每个表头赋值,从0开始
for (int i = 0; i <= table1->data - 1; ++i)
{
table1->firstedge [i] = static_cast<position>(malloc(sizeof(EdgeNode))); //申请一个节点
if (table1->firstedge [i] == NULL)
{
cout << "out of space!!!";
}
table1->firstedge [i]->adjvex = 0; //表头这个参数存储入度
table1->firstedge [i]->weight = 0; //此参数在此时没有意义
table1->firstedge [i]->next = NULL; }
return table1; } void Insert (Table table1, int v, int w, int weig) //表示存在一条边为<v,w>,且权重为weig
{
position p = static_cast<position>(malloc(sizeof(EdgeNode))); //申请一个节点
if(p == NULL)
{
cout << "out of space!!!";
}
p->adjvex = w;
p->weight = weig;
p->next = table1->firstedge [v]->next;
table1->firstedge [v]->next = p; } /////////////////////单源无权算法相关定义/////////////////////////
typedef struct unweight_path *unweight_node ; struct unweight_path //
{
bool know;
int dist; // 邻接点域,存储该顶点对应的下标
int path; // 对应边的权值
}; unweight_node unweight_init(Table table1, int start) //节点初始化
{
unweight_node Node = static_cast<unweight_node>(malloc(sizeof(unweight_path)*(table1->data)));
if (Node == NULL)
{
cout << "out of space!!!";
}
for(int i = 0; i != table1->data; ++i)
{
Node[i].know = false;
Node[i].dist = Inf;
Node[i].path = NotAVerter;
}
Node[start].dist = 0;
return Node;
} ////////////////////////单源有权最短路径算法 Dijkstra ///////////////////////////// void Dijkstra_Algorithm (Table table1,unweight_node Node)
{
int v;
//用了两次for循环,时间复杂度较高
for (int j = 0; j != table1->data; ++j)
{
int zh = Inf;
for (int i = 0; i != table1->data; ++i) //找路径最小且没有标记过的点
{
if(!Node[i].know && zh > Node[i].dist ) //如果这个点是未知的,且距离比较小
{
zh = Node[i].dist;
v = i;
} }
//此时v是距离最小的那个点
Node[v].know = true; //标记这个点
position p = table1->firstedge [v]->next;
while (p != NULL) //与这个节点有连接的距离+1
{
if(!Node[p->adjvex].know && Node[v].dist + p->weight < Node[p->adjvex].dist )
{
Node[p->adjvex].dist = Node[v].dist + p->weight;
Node[p->adjvex].path = v;
}
p = p->next;
} } } /////////////////////打印实际的有权最短路径///////////////////////////////
//采用递归算法,从后往前推
void PrintPath (int v, unweight_node Node)
{
if(Node[v].path != NotAVerter)
{
PrintPath (Node[v].path ,Node);
cout << " -> "; }
cout << "v" << v;
} int main ()
{
Table table_1 = Creat_Lable (7); //创建一个大小为7的邻接表 //根据图来为邻接表插入数据 Insert (table_1, 0, 1, 2);Insert (table_1, 0, 2, 4);Insert (table_1, 0, 3, 1);
Insert (table_1, 1, 3, 3);Insert (table_1, 1, 4, 10);
Insert (table_1, 2, 5, 5);
Insert (table_1, 3, 2, 2);Insert (table_1, 3, 5, 8);Insert (table_1, 3, 6, 4);
Insert (table_1, 4, 3, 2);Insert (table_1, 4, 6, 6);
Insert (table_1, 6, 5, 1); unweight_node Node_1 = unweight_init(table_1, 0); //初始化节点 Dijkstra_Algorithm (table_1, Node_1);
for (int i = 0; i != table_1->data; ++i)
{
cout << Node_1[i].dist << '\t';
}
cout << endl;
PrintPath (6, Node_1);
while(1);
return 0;
}

  

  对于下图来说

以v0为起点,到各点的最短路径为:

下面的v0->v3->v6表示v0到v6的最短路径经过的点。

Dijkstra算法是典型的贪婪算法,并不能保证100%的正确率。

也可参考 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html  这篇博客的思想,本质上差不多。

夜深了.....

有向有权图的最短路径算法--Dijkstra算法的更多相关文章

  1. python数据结构与算法——图的最短路径(Dijkstra算法)

    # Dijkstra算法——通过边实现松弛 # 指定一个点到其他各顶点的路径——单源最短路径 # 初始化图参数 G = {1:{1:0, 2:1, 3:12}, 2:{2:0, 3:9, 4:3}, ...

  2. 带权图的最短路径算法(Dijkstra)实现

    一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...

  3. 最短路径之Dijkstra算法及实例分析

    Dijkstra算法迪科斯彻算法 Dijkstra算法描述为:假设用带权邻接矩阵来表示带权有向图.首先引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点Vi的最短路径.它的初始 ...

  4. 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)

    一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...

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

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

  6. 单源点最短路径的Dijkstra算法

    在带权图(网)里,点A到点B所有路径中边的权值之和为最短的那一条路径,称为A,B两点之间的最短路径;并称路径上的第一个顶点为源点(Source),最后一个顶点为终点(Destination).在无权图 ...

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

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

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

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

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

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

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

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

随机推荐

  1. [OS] 多线程--原子操作 Interlocked系列函数

    转自:http://blog.csdn.net/morewindows/article/details/7429155 上一篇<多线程--第一次亲密接触 CreateThread与_begint ...

  2. iOS-学习UIKIt框架的重要性

      前言: 众所周知,我们的移动设备的屏幕上可以展示很多图形界面,作为用户的我们可以通过屏幕上的图形界面浏览信息,也可以通过与图形界面的简单交互,在移动设备上实现各种各样的功能操作.....可以说,没 ...

  3. 【bzoj2502】清理雪道 有上下界最小流

    题目描述 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞 ...

  4. BZOJ4784 ZJOI2017仙人掌(树形dp+dfs树)

    首先考虑是棵树的话怎么做.可以发现相当于在树上选择一些长度>=2的路径使其没有交,同时也就相当于用一些没有交的路径覆盖整棵树. 那么设f[i]为覆盖i子树的方案数.转移时考虑包含根的路径.注意到 ...

  5. hadoop 使用map将SequenFile里的小文件解压出来

    上例中将HDFS里小文件通过mapper压缩到一个文件中,本例将这些小文件解压出来. mapreduce可以按SequenceFile的key进行分片. 1.mapper public class M ...

  6. CentOS LVM逻辑卷管理

    在CentOS 挂载(U盘NTFS格式,新硬盘,增加交换分区,扩展根分区等)中扩展根分区部分用的就是LVM逻辑卷管理来进行扩展的. 1.为什么会有逻辑卷管理 传统磁盘管理是直接对硬盘分区进行访问,你如 ...

  7. HDU.1233 还是畅通工程(Prim)

    HDU.1233 还是畅通工程(Prim) 题意分析 首先给出n,代表村庄的个数 然后出n*(n-1)/2个信息,每个信息包括村庄的起点,终点,距离, 要求求出最小生成树的权值之和. 注意村庄的编号从 ...

  8. bzoj1004: [HNOI2008]Cards(burnside引理+DP)

    题目大意:3种颜色,每种染si个,有m个置换,求所有本质不同的染色方案数. 置换群的burnside引理,还有个Pólya过几天再看看... burnside引理:有m个置换k种颜色,所有本质不同的染 ...

  9. Application Error - The connection to the server was unsuccessful. (file:///android_asset/www/index.html)

    问题描述: PhoneGap+Sencha Touch开发的应用,打包后的APP或者调试期间,在启动的时候提示如下信息: Application Error - The connection to t ...

  10. Ruby环境搭建

    刚接触Ruby,发现Ruby真心强大,搞了那么久的Java了,已经被Java的繁琐的语法整的无语透顶了,尤其的Java异常,设计出来就是个失败呀!Ruby目前更新到了2.x了,社区也很活跃,开发效率和 ...