C/C++最短路径算法之迪杰斯特拉Dijkstra的实现详解

目录
  • 前言
  • 一、迪杰斯特拉(Dijkstra)算法是什么
  • 二、实现步骤
    • 1.算法思路
    • 2.进入主函数ShortestPath()
      • 1.创建final数组并且初始化path[]、dist[]数组
      • 2.对于节点的初始化
      • 3.进入主循环
  • 三、全部代码(邻接表下)
  • 四、全部代码(邻接矩阵下)
  • 五、测试代码(邻接表下)
  • 总结

前言

我们在生活中常常面临对路径选择的决策问题,这就要用到最短路径的算法了。

对于我这种榆木脑袋,显然迪杰斯特拉的这种算法有点高深。主要是我笨。

对于网图来说,最短路径,就是指两个顶点之间经过的边上权值之和最小的路径,并且我们称路径上的第一个顶点就是源点,最后一个顶点式终点。

一、迪杰斯特拉(Dijkstra)算法是什么

迪杰斯特拉算法是一个按照路径长度递增的次序产生最短路径的算法。

二、实现步骤

1.算法思路

这里先采用邻接表来遍历。

在遍历节点时,找到未遍历节点中权值最小的进行遍历,并且及时更新最短路径长度dist数组[]。

首先设置path[]数组代表路径信息。 dist[] 表示最短路径长度。

int* path = (int*)malloc(sizeof(G.vexnum));
int* dist = (int*)malloc(sizeof(G.vexnum));

2.进入主函数ShortestPath()

1.创建final数组并且初始化path[]、dist[]数组

final数组来表示是否完成对该节点的最短路径求解。final[v]==1表示完成最短路径搜素,反之final[vi]==0表示未完成。

在算法中只有在求得最短路径后才会将final[vi]置为1,也可以简单理解为访问标志数组。

path数组全体初始化为0。

final数组因为最开始并没有完成最短路径求解,故置为0。

dist数组初始化为与vi相连的节点的权值,没连就是INFINITY(65535)。

int* final = (int*)malloc(sizeof(int) * g.vexnum);
	for (int i = 0; i < g.vexnum; i++) {
		path[i] = 0;
		final[i] = 0;
		dist[i] = INFNITY;
	}
	ArcNode* p = g.vertexlist[vi].firstarc;
	for (p; p != NULL; p = p->nextarc) {
		dist[p->adjvex] = p->weight;
	}

2.对于节点的初始化

在遍历vi节点时,vi到vi的路径为0,vi到vi之间也不需要求路径,故dist[vi]=0;final[vi]=1;

dist[vi] = 0;
final[vi] = 1;

肯定有人问,那path呢,path代表路径信息,vi时源点自然就是0了,当然初始化时也可以把path全初始化为-1,看个人习惯了。

3.进入主循环

将对刨掉源点的其他节点进行遍历,故外循环次数为g.vexnum-1次。

再在dist数组中找到权值最小并且未完成最短路径搜索的节点,用k来表示该节点下标。

其次找到最小权值k节点后,设置final[k]=1,再对k节点进行遍历,更新dist和path数组。

更新方法:若与k节点相连的节点未完成最短路径搜索并且k节点权值+该节点权值小于dist数组中的源点到该节点的最短路径,那么将更新dist数组中到该节点的最短路径,并且更新path数组,到该节点的前驱为k节点。

	int k;
	for (int v = 1; v < g.vexnum; v++) {
		int min = INFNITY;
		for (int w = 0; w < g.vexnum; w++) {
			if (!final[w] && dist[w] < min) {
				k = w;
				min = dist[w];
			}
		}
		final[k] = 1;
		ArcNode* p = g.vertexlist[k].firstarc;
		while (p != NULL) {
			if (!final[p->adjvex] && (p->weight + min) < dist[p->adjvex]) {
				dist[p->adjvex] = min + p->weight;
				path[p->adjvex] = k;
			}
			p = p->nextarc;
		}
	}

三、全部代码(邻接表下)

void ShortestPath(AdjList g, int vi, int* path, int* dist) {
	int* final = (int*)malloc(sizeof(int) * g.vexnum);
	for (int i = 0; i < g.vexnum; i++) {
		path[i] = 0;
		final[i] = 0;
		dist[i] = INFNITY;
	}
	ArcNode* p = g.vertexlist[vi].firstarc;
	for (p; p != NULL; p = p->nextarc) {
		dist[p->adjvex] = p->weight;
	}
	dist[vi] = 0;
	final[vi] = 1;
	int k;
	for (int v = 1; v < g.vexnum; v++) {
		int min = INFNITY;
		for (int w = 0; w < g.vexnum; w++) {
			if (!final[w] && dist[w] < min) {
				k = w;
				min = dist[w];
			}
		}
		final[k] = 1;
		ArcNode* p = g.vertexlist[k].firstarc;
		while (p != NULL) {
			if (!final[p->adjvex] && (p->weight + min) < dist[p->adjvex]) {
				dist[p->adjvex] = min + p->weight;
				path[p->adjvex] = k;
			}
			p = p->nextarc;
		}
	}
	free(final);
	return;
}

四、全部代码(邻接矩阵下)

思路大同小异,在初始化时有些不同,其他很相像。

void ShortestPath(AdjMatrix g, int vi, int* path, int* dist) {
	int* final = (int*)malloc(sizeof(int) * g.vexnum);
	for (int i = 0; i < g.vexnum; i++) {
		path[i] = 0;
		final[i] = 0;
		dist[i] = g.arc[vi][i];
	}
	dist[vi] = 0;
	final[vi] = 1;
	int k;
	for (int v = 1; v < g.vexnum; v++) {
		int min = INFNITY;
		for (int w = 0; w < g.vexnum; w++) {
			if (!final[w] && dist[w] < min) {
				k = w;
				min = dist[w];
			}
		}
		final[k] = 1;
		ArcNode* p = g.vertexlist[k].firstarc;
		for (int w = 0; w < g.vexnum; w++) {
			if (!final[w] && (min+g.arc[k][w])<dist[w]) {
				dist[w]=min+g.arc[k][w];
				path[w]=k;
			}
		}
	}
	free(final);
	return;
}

五、测试代码(邻接表下)

这里就测试一个邻接表下的。

自己花了个图

因为我的边表建立的时候A是第一个,自然A就是源点。

结果如下

很完美。

总结

很显然这个算法的时间复杂度是O(n²),如果要知道任意顶点到其余所有顶点的最短路径,那么就可以对每一个顶点当作源点进行一次迪杰斯特拉算法。这时候后整个算法的时间复杂度也就成了O(n³)。这个和弗洛伊德算法的时间复杂度一样,但弗洛伊德算法那是相当的优雅。

到此这篇关于C/C++最短路径算法之迪杰斯特拉Dijkstra的实现详解的文章就介绍到这了,更多相关C/C++迪杰斯特拉内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++求所有顶点之间的最短路径(用Dijkstra算法)

    本文实例为大家分享了C++求所有顶点之间最短路径的具体代码,供大家参考,具体内容如下 一.思路: 不能出现负权值的边 (1)轮流以每一个顶点为源点,重复执行Dijkstra算法n次,就可以求得每一对顶点之间的最短路径及最短路径长度,总的执行时间为O(n的3次方) (2)另一种方法:用Floyd算法,总的执行时间为O(n的3次方)(另一文章会写) 二.实现程序: 1.Graph.h:有向图 #ifndef Graph_h #define Graph_h #include <iostream> u

  • Dijkstra算法最短路径的C++实现与输出路径

    某个源点到其余各顶点的最短路径 这个算法最开始心里怕怕的,不知道为什么,花了好长时间弄懂了,也写了一遍,又遇到时还是出错了,今天再次写它,心里没那么怕了,耐心研究,懂了之后会好开心的,哈哈 Dijkstra算法: 图G 如图:若要求从顶点1到其余各顶点的最短路径,该咋求: 迪杰斯特拉提出"按最短路径长度递增的次序"产生最短路径. 首先,在所有的这些最短路径中,长度最短的这条路径必定只有一条弧,且它的权值是从源点出发的所有弧上权的最小值,例如:在图G中,从源点1出发有3条弧,其中以弧(1

  • 详解Dijkstra算法原理及其C++实现

    目录 什么是最短路径问题 Dijkstra算法 实现思路 案例分析 代码实现 什么是最短路径问题 如果从图中某一顶点(称为源点)到达另一顶点(称为终点)的路径可能不止一条,如何找到一条路径使得沿此路径上各边上的权值总和达到最小. 单源最短路径问题是指对于给定的图G=(V,E),求源点v0到其它顶点vt的最短路径. Dijkstra算法 Dijkstra算法用于计算一个节点到其他节点的最短路径.Dijkstra是一种按路径长度递增的顺序逐步产生最短路径的方法,是一种贪婪算法. Dijkstra算法

  • C++实现Dijkstra算法

    本文实例为大家分享了C++实现Dijkstra算法的具体代码,供大家参考,具体内容如下 #include <iostream> #include <limits> using namespace std; struct Node { //定义表结点 int adjvex; //该边所指向的顶点的位置 int weight;// 边的权值 Node *next; //下一条边的指针 }; struct HeadNode{ // 定义头结点 int nodeName; // 顶点信息

  • C++ Dijkstra算法之求图中任意两顶点的最短路径

    Dijkstra算法是图中找任意两点中最短路径的一种经典算法. 重点的步骤总结如下: 1.算法采用了并查集 (之后都叫它为 最短路径顶点集 ):即每次都找离开始顶点距离最短的顶点,然后把该顶点加入最短路径顶点集中(已经加入最短路径顶点集里的那些顶点 下一次就会跳过它了,并且,在顶点集里 任意两个顶点间的距离 都已经是最短) 2.用来记录从源点(开始顶点) 到vi (0<=i<=numVertices) 的最短距离 的数组dist[numVertices] ,并且这个数组的元素值是会不断变化的,

  • C++简单实现Dijkstra算法

    本文实例为大家分享了C++简单实现Dijkstra算法的具体代码,供大家参考,具体内容如下 // Dijkstra.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include <stack> #define MAX_VALUE 1000 using namespace std; struct MGraph { int *edges[MAX_VALUE]; int iVertex

  • C++用Dijkstra(迪杰斯特拉)算法求最短路径

    算法介绍 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低. 算法思想 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的集合(初始时只含有源点V0) (2)V-S=T:尚未确定的顶点集合 将T中顶点按递增

  • C++实现Dijkstra(迪杰斯特拉)算法

    Dijkstra算法 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,是广度优先算法的一种,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离.当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性.不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破

  • C++实现Dijkstra算法的示例代码

    目录 一.算法原理 二.具体代码 1.graph类 2.PathFinder类 3. main.cpp 三.示例 一.算法原理 链接: Dijkstra算法及其C++实现参考这篇文章 二.具体代码 1.graph类 graph类用于邻接表建立和保存有向图. graph.h: #ifndef GRAPH_H #define GRAPH_H #include <iostream> #include <string> #include <vector> #include &l

  • C/C++最短路径算法之迪杰斯特拉Dijkstra的实现详解

    目录 前言 一.迪杰斯特拉(Dijkstra)算法是什么 二.实现步骤 1.算法思路 2.进入主函数ShortestPath() 1.创建final数组并且初始化path[].dist[]数组 2.对于节点的初始化 3.进入主循环 三.全部代码(邻接表下) 四.全部代码(邻接矩阵下) 五.测试代码(邻接表下) 总结 前言 我们在生活中常常面临对路径选择的决策问题,这就要用到最短路径的算法了. 对于我这种榆木脑袋,显然迪杰斯特拉的这种算法有点高深.主要是我笨. 对于网图来说,最短路径,就是指两个顶

  • java图论弗洛伊德和迪杰斯特拉算法解决最短路径问题

    目录 弗洛伊德算法 算法介绍 算法图解分析   迪杰斯特拉算法 算法介绍 算法过程  弗洛伊德算法 算法介绍 算法图解分析     第一轮循环中,以A(下标为:0)作为中间顶点 [即把作为中间顶点的所有情况都进行遍历,就会得到更新距离表和前驱关系],距离表和前驱关系更新为: 弗洛伊德算法和迪杰斯特拉算法的最大区别是: 弗洛伊德算法是从各个顶点出发,求最短路径: 迪杰斯特拉算法是从某个顶点开始,求最短路径. /** * 弗洛伊德算法 * 容易理解,容易实现 */ public void floyd

  • Java 迪杰斯特拉算法实现查找最短距离的实现

    迪杰斯特拉算法 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.具体的计算规则我们可以通过下图进行查看. 通过这幅图我们可以简单的理解迪杰斯特拉算法算法的基础思路,下面我们就通过JAVA来实现这个算法. 算法实现 在迪杰斯特拉算法中我们需要保存从起点开始到每一个节点最短步长,这也是图中需要比较得出的步长,同时我们还

  • Python实现迪杰斯特拉算法并生成最短路径的示例代码

    def Dijkstra(network,s,d):#迪杰斯特拉算法算s-d的最短路径,并返回该路径和代价 print("Start Dijstra Path--") path=[]#s-d的最短路径 n=len(network)#邻接矩阵维度,即节点个数 fmax=999 w=[[0 for i in range(n)]for j in range(n)]#邻接矩阵转化成维度矩阵,即0→max book=[0 for i in range(n)]#是否已经是最小的标记列表 dis=[

  • 基于Python实现迪杰斯特拉和弗洛伊德算法

    图搜索之基于Python的迪杰斯特拉算法和弗洛伊德算法,供大家参考,具体内容如下 Djstela算法 #encoding=UTF-8 MAX=9 ''' Created on 2016年9月28日 @author: sx ''' b=999 G=[[0,1,5,b,b,b,b,b,b],\ [1,0,3,7,5,b,b,b,b],\ [5,3,0,b,1,7,b,b,b],\ [b,7,b,0,2,b,3,b,b],\ [b,5,1,2,0,3,6,9,b],\ [b,b,7,b,3,0,b,5

  • Python实现迪杰斯特拉算法过程解析

    一. 迪杰斯特拉算法思想 Dijkstra算法主要针对的是有向图的单元最短路径问题,且不能出现权值为负的情况!Dijkstra算法类似于贪心算法,其应用根本在于最短路径的最优子结构性质. 最短路径的最优子结构性质: 如果P(i,j)={Vi-Vk-Vs-Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径. 证明: 假设P(i,j)={Vi-Vk-Vs-Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,j)

  • 详解Java中Dijkstra(迪杰斯特拉)算法的图解与实现

    目录 简介 工作过程 总体思路 实现 小根堆 Dijsktra 测试 简介 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边.对应问题:在无向图G=(V,E)中,假设每条边E(i)的长度W(i),求由顶点V0到各节点的最短路径. 工作过

  • js图数据结构处理 迪杰斯特拉算法代码实例

    这篇文章主要介绍了js图数据结构处理 迪杰斯特拉算法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 /*//1.确定数据结构, mapf[i][j] 为点i到点j的距离 [ Infinity 2 5 Infinity Infinity Infinity Infinity 2 6 Infinity Infinity Infinity Infinity 7 1 Infinity Infinity 2 Infinity 4 Infinity

随机推荐