有向有权图的最短路径算法--Dijkstra算法
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算法的更多相关文章
- python数据结构与算法——图的最短路径(Dijkstra算法)
# Dijkstra算法——通过边实现松弛 # 指定一个点到其他各顶点的路径——单源最短路径 # 初始化图参数 G = {1:{1:0, 2:1, 3:12}, 2:{2:0, 3:9, 4:3}, ...
- 带权图的最短路径算法(Dijkstra)实现
一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...
- 最短路径之Dijkstra算法及实例分析
Dijkstra算法迪科斯彻算法 Dijkstra算法描述为:假设用带权邻接矩阵来表示带权有向图.首先引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点Vi的最短路径.它的初始 ...
- 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)
一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...
- 数据结构与算法--最短路径之Dijkstra算法
数据结构与算法--最短路径之Dijkstra算法 加权图中,我们很可能关心这样一个问题:从一个顶点到另一个顶点成本最小的路径.比如从成都到北京,途中还有好多城市,如何规划路线,能使总路程最小:或者我们 ...
- 单源点最短路径的Dijkstra算法
在带权图(网)里,点A到点B所有路径中边的权值之和为最短的那一条路径,称为A,B两点之间的最短路径;并称路径上的第一个顶点为源点(Source),最后一个顶点为终点(Destination).在无权图 ...
- 最短路径 | 深入浅出Dijkstra算法(一)
参考网址: https://www.jianshu.com/p/8b3cdca55dc0 写在前面: 上次我们介绍了神奇的只有五行的 Floyd-Warshall 最短路算法,它可以方便的求得任意两点 ...
- 经典树与图论(最小生成树、哈夫曼树、最短路径问题---Dijkstra算法)
参考网址: https://www.jianshu.com/p/cb5af6b5096d 算法导论--最小生成树 最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树. im ...
- 单源最短路径(dijkstra算法)php实现
做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...
- 【算法设计与分析基础】25、单起点最短路径的dijkstra算法
首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...
随机推荐
- C的强制转换和C++的强制转换(转)
C的强制转换: (type)<expression> 其中,type为类型描述符,如int,float等.<expression>为表达式.经强制类型转换运算符运算后,返回一个 ...
- 第三章 AOP
什么是AOP AOP的编写方式 什么是AOP? 是一种面向切面的思想,关注的是切面中的相似功能,将这些功能抽离出来,提高代码的复用性 AOP术语 advice-通知:要执行的任务 Spring切面有5 ...
- 【bzoj2699】更新 dp
题目描述 对于一个数列A[1..N],一种寻找最大值的方法是:依次枚举A[2]到A[N],如果A[i]比当前的A[1]值要大,那么就令A[1]=A[i],最后A[1]为所求最大值.假设所有数都在范围[ ...
- HTML5 不再支持哪些元素
HTML5中已经不支持以下的元素,不建议在进行开发时再使用以下的元素. 1.acronym(建议abbr):定义首字母缩写 2.applet(建议object):定义applet 3.basefont ...
- 去除安卓手机select下拉框默认箭头
-webkit-appearance: listbox;
- 关于Python的 a, b = b, a+b
Python中有一种写法:多个值同时赋给多个变量,如:a, b = b, a+b 1. A写法 a = 0, b = 1 a, b = b, a+b print a, b #结果为:1 1 这种写法, ...
- Oracle数据库表被锁定以及去除方式
select t2.username, t2.sid, t2.serial#, t3.object_name, t2.OSUSER, t2.MACHINE, t2.PROGRAM, t2.LOGON_ ...
- BZOJ1502:[NOI2005]月下柠檬树——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1502 https://www.luogu.org/problemnew/show/P4207 李哲 ...
- BZOJ3714 [PA2014]Kuglarz 【最小生成树】
题目链接 BZOJ3714 题解 我们如果知道了所有的数,同样就知道了所有的前缀和 相反,我们如果求出了所有前缀和,就知道了所有的数,二者是等价的 对于一个区间\([l,r]\)如果我们知道了前缀和\ ...
- POJ.1006 Biorhythms (拓展欧几里得+中国剩余定理)
POJ.1006 Biorhythms (拓展欧几里得+中国剩余定理) 题意分析 不妨设日期为x,根据题意可以列出日期上的方程: 化简可得: 根据中国剩余定理求解即可. 代码总览 #include & ...