Dijkstra算法是一种求单源最短路的算法,即从一个点开始到所有其他点的最短路。其步骤如下:

c语言实现如下:(使用邻接矩阵存储)

#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 6 //存放最短路径的边元素
typedef struct edge{
int vertex;
int value;
struct edge* next;
}st_edge; void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value);
void displayGraph(int (*edge)[VERTEXNUM]);
void displayPath(st_edge** path, int startVertex,int* shortestPath);
void dijkstra(int (*edge)[VERTEXNUM], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr);
int getDistance(int value, int startVertex, int start, int* shortestPath);
void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue); int main(void){
//动态创建存放边的二维数组
int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);
int i,j;
for(i=0;i<VERTEXNUM;i++){
for(j=0;j<VERTEXNUM;j++){
edge[i][j] = 0;
}
}
//存放顶点的遍历状态,0:未遍历,1:已遍历
int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
for(i=0;i<VERTEXNUM;i++){
vertexStatusArr[i] = 0;
} printf("after init:\n");
displayGraph(edge);
//创建图
createGraph(edge,0,1,6);
createGraph(edge,0,3,5);
createGraph(edge,0,2,1);
createGraph(edge,1,2,5);
createGraph(edge,1,4,3);
createGraph(edge,2,4,6);
createGraph(edge,2,3,5);
createGraph(edge,2,5,4);
createGraph(edge,3,5,2);
createGraph(edge,4,5,6); printf("after create:\n");
displayGraph(edge);
//最短路径
/*存储的结构如下:
path[0]:edge0->NULL
path[1]:edge1->NULL
path[2]:edge1->edge2->NULL
path[3]:edge1->edge2->edge3->NULL
path[4]:edge4->NULL
从顶点0到0的最短路径:从0出发直接到0
从顶点0到1的最短路径:从0出发直接到1
从顶点0到2的最短路径:从0出发到1,从1出发到2
......
*/
st_edge** path = NULL;
//存储最短路径的权值
/*
shortestPath[0] = 0;
shortestPath[1] = 8;
shortestPath[2] = 12;
从顶点0到0的路径是0
从顶点0到1的路径是8
从顶点0到2的路径是12
*/
int* shortestPath = NULL;
//从顶点0开始寻找最短路径
int startVertex = 0;
//最短路径
dijkstra(edge, &path, &shortestPath, startVertex, vertexStatusArr);
printf("the path is:\n");
displayPath(path,startVertex,shortestPath); free(edge);
free(path);
return 0;
}
//创建图
void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value){
edge[start][end] = value;
edge[end][start] = value;
}
//打印存储的图
void displayGraph(int (*edge)[VERTEXNUM]){
int i,j;
for(i=0;i<VERTEXNUM;i++){
for(j=0;j<VERTEXNUM;j++){
printf("%d ",edge[i][j]);
}
printf("\n");
}
}
//打印最短路径
void displayPath(st_edge** path, int startVertex,int* shortestPath){
int i;
st_edge* p;
for(i=0;i<VERTEXNUM;i++){
printf("Path from %d to %d:",startVertex,i);
p = *(path+i);
while(p != NULL){
printf("%d(%d) ",p->vertex,p->value);
p = p->next;
}
printf("\n");
printf("the count is:%d\n",shortestPath[i]);
}
}
//最短路径
void dijkstra(int (*edge)[VERTEXNUM], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr){
//初始化最短路径
*path = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
int i,j;
for(i=0;i<VERTEXNUM;i++){
if(i == startVertex){
st_edge* e = (st_edge*)malloc(sizeof(st_edge));
e->vertex = startVertex;
e->value = 0;
e->next = NULL;
(*path)[i] = e;
}else{
(*path)[i] = NULL;
}
}
//初始化最短路径的权值
*shortestPath = (int *)malloc(sizeof(int)*VERTEXNUM);
for(i=0;i<VERTEXNUM;i++){
if(i == startVertex){
(*shortestPath)[i] = 0;
}else{
(*shortestPath)[i] = -1;
}
}
//从顶点0开始,则顶点0就是已访问的
vertexStatusArr[startVertex] = 1; int shortest, distance,start, end, edgeValue, vNum = 1;
//如果还顶点还没有访问完
while(vNum < VERTEXNUM){
shortest = 9999;
for(i=0;i<VERTEXNUM;i++){
//选择已经访问过的点
if(vertexStatusArr[i] == 1){
for(j=0;j<VERTEXNUM;j++){
//选择一个没有访问过的点
if(vertexStatusArr[j] == 0){
//选出一条value最小的边
if(edge[i][j] != 0 && (distance = getDistance(edge[i][j], startVertex, i, *shortestPath)) < shortest){
shortest = distance;
edgeValue = edge[i][j];
start = i;
end = j;
}
}
}
}
}
vNum++;
//将点设置为访问过
vertexStatusArr[end] = 1;
//保存最短路径权值
(*shortestPath)[end] = shortest;
//保存最短路径
createPath(*path, startVertex, start, end, edgeValue);
}
} //返回从startVertex到新的顶点的距离
int getDistance(int value, int startVertex, int start, int* shortestPath){
if(start == startVertex){
return value;
}else{
return shortestPath[start] + value;
}
} //保存最短路径
void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue){
if(start == startVertex){
st_edge* newEdge = (st_edge*)malloc(sizeof(st_edge));
newEdge->vertex = end;
newEdge->value = edgeValue;
newEdge->next = NULL; st_edge** p = path + end;
while((*p) != NULL){
p = &((*p)->next);
}
*p = newEdge;
}else{
st_edge** pCopySrc = path + start;
st_edge** pCopyDes = path + end;
st_edge* newEdge = NULL;
while((*pCopySrc) != NULL){
newEdge = (st_edge*)malloc(sizeof(st_edge));
*newEdge = **pCopySrc;
newEdge->next = NULL;
*pCopyDes = newEdge;
pCopySrc = &((*pCopySrc)->next);
pCopyDes = &((*pCopyDes)->next);
}
newEdge = (st_edge*)malloc(sizeof(st_edge));
newEdge->vertex = end;
newEdge->value = edgeValue;
newEdge->next = NULL;
*pCopyDes = newEdge;
}
}

c语言实现如下:(使用邻接表存储)

#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 6 //存放顶点的邻接表元素
//存放最短路径的边元素
typedef struct edge{
int vertex;
int value;
struct edge* next;
}st_edge; void createGraph(st_edge** edge, int start, int end, int value);
void displayGraph(st_edge** edge);
void delGraph(st_edge** edge);
void dijkstra(st_edge** edge, st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr);
void displayPath(st_edge** path, int startVertex,int* shortestPath);
int getDistance(int value, int startVertex, int start, int* shortestPath);
void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue); int main(void){
//动态创建存放边的指针数组
st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
int i;
for(i=0;i<VERTEXNUM;i++){
edge[i] = NULL;
}
//存放顶点的遍历状态,0:未遍历,1:已遍历
int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
for(i=0;i<VERTEXNUM;i++){
vertexStatusArr[i] = 0;
} printf("after init:\n");
displayGraph(edge);
//创建图
createGraph(edge,0,1,6);
createGraph(edge,0,3,5);
createGraph(edge,0,2,1);
createGraph(edge,1,2,5);
createGraph(edge,1,4,3);
createGraph(edge,2,4,6);
createGraph(edge,2,3,5);
createGraph(edge,2,5,4);
createGraph(edge,3,5,2);
createGraph(edge,4,5,6); printf("after create:\n");
displayGraph(edge); //最短路径
/*存储的结构如下:
path[0]:edge0->NULL
path[1]:edge1->NULL
path[2]:edge1->edge2->NULL
path[3]:edge1->edge2->edge3->NULL
path[4]:edge4->NULL
从顶点0到0的最短路径:从0出发直接到0
从顶点0到1的最短路径:从0出发直接到1
从顶点0到2的最短路径:从0出发到1,从1出发到2
......
*/
st_edge** path = NULL;
//存储最短路径的权值
/*
shortestPath[0] = 0;
shortestPath[1] = 8;
shortestPath[2] = 12;
从顶点0到0的路径是0
从顶点0到1的路径是8
从顶点0到2的路径是12
*/
int* shortestPath = NULL;
int startVertex = 0;
//最短路径
dijkstra(edge, &path, &shortestPath, startVertex, vertexStatusArr);
printf("the path is:\n");
displayPath(path,startVertex,shortestPath); delGraph(edge);
edge = NULL; delGraph(path);
path = NULL; if(vertexStatusArr != NULL){
free(vertexStatusArr);
vertexStatusArr = NULL;
} if(shortestPath != NULL){
free(shortestPath);
shortestPath = NULL;
}
return 0;
}
//创建图
void createGraph(st_edge** edge, int start, int end, int value){
st_edge* newedge1 = (st_edge*)malloc(sizeof(st_edge));
newedge1->vertex = end;
newedge1->value = value;
newedge1->next = NULL;
st_edge** edge1 = edge + start;
while(*edge1 != NULL){
edge1 = &((*edge1)->next);
}
*edge1 = newedge1; st_edge* newedge2 = (st_edge*)malloc(sizeof(st_edge));
newedge2->vertex = start;
newedge2->value = value;
newedge2->next = NULL;
st_edge** edge2 = edge + end;
while(*edge2 != NULL){
edge2 = &((*edge2)->next);
}
*edge2 = newedge2;
}
//打印存储的图
void displayGraph(st_edge** edge){
int i;
st_edge* p;
for(i=0;i<VERTEXNUM;i++){
printf("%d:",i);
p = *(edge+i);
while(p != NULL){
printf("%d(%d) ",p->vertex,p->value);
p = p->next;
}
printf("\n");
}
}
//打印最短路径
void displayPath(st_edge** path, int startVertex,int* shortestPath){
int i;
st_edge* p;
for(i=0;i<VERTEXNUM;i++){
printf("Path from %d to %d:",startVertex,i);
p = *(path+i);
while(p != NULL){
printf("%d(%d) ",p->vertex,p->value);
p = p->next;
}
printf("\n");
printf("the count is:%d\n",shortestPath[i]);
}
}
//释放邻接表占用的内存
void delGraph(st_edge** edge){
int i;
st_edge* p;
st_edge* del;
for(i=0;i<VERTEXNUM;i++){
p = *(edge+i);
while(p != NULL){
del = p;
p = p->next;
free(del);
}
edge[i] = NULL;
}
free(edge);
}
//dijkstra求最短路径
void dijkstra(st_edge** edge, st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr){
//初始化最短路径
*path = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
int i,j;
for(i=0;i<VERTEXNUM;i++){
if(i == startVertex){
st_edge* e = (st_edge*)malloc(sizeof(st_edge));
e->vertex = startVertex;
e->value = 0;
e->next = NULL;
(*path)[i] = e;
}else{
(*path)[i] = NULL;
}
}
//初始化最短路径的权值
*shortestPath = (int *)malloc(sizeof(int)*VERTEXNUM);
for(i=0;i<VERTEXNUM;i++){
if(i == startVertex){
(*shortestPath)[i] = 0;
}else{
(*shortestPath)[i] = -1;
}
} vertexStatusArr[startVertex] = 1; st_edge* p;
int shortest, distance, edgeValue, start, end, vNum = 1;
//如果还顶点还没有访问完
while(vNum < VERTEXNUM){
shortest = 9999;
for(i=0;i<VERTEXNUM;i++){
//选择已经访问过的点
if(vertexStatusArr[i] == 1){
for(j=0;j<VERTEXNUM;j++){
//选择一个没有访问过的点
if(vertexStatusArr[j] == 0){
p = *(edge+i);
while(p != NULL){
//如果从startVertex到j的距离小于shortest
if((distance = getDistance(p->value, startVertex, i, *shortestPath)) < shortest && p->vertex == j){
shortest = distance;
edgeValue = p->value;
start = i;
end = j;
}
p = p->next;
}
}
}
}
}
vNum++;
vertexStatusArr[end] = 1;
//保存最短路径的权值
(*shortestPath)[end] = shortest;
//保存最短路径
createPath(*path, startVertex, start, end, edgeValue);
}
}
//返回从startVertex到新的顶点的距离
int getDistance(int value, int startVertex, int start, int* shortestPath){
if(start == startVertex){
return value;
}else{
return value + shortestPath[start];
}
}
//保存最短路径
void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue){
if(start == startVertex){
st_edge* newEdge = (st_edge*)malloc(sizeof(st_edge));
newEdge->vertex = end;
newEdge->value = edgeValue;
newEdge->next = NULL; st_edge** p = path + end;
while((*p) != NULL){
p = &((*p)->next);
}
*p = newEdge;
}else{
st_edge** pCopySrc = path + start;
st_edge** pCopyDes = path + end;
st_edge* newEdge = NULL;
while((*pCopySrc) != NULL){
newEdge = (st_edge*)malloc(sizeof(st_edge));
*newEdge = **pCopySrc;
newEdge->next = NULL;
*pCopyDes = newEdge;
pCopySrc = &((*pCopySrc)->next);
pCopyDes = &((*pCopyDes)->next);
}
newEdge = (st_edge*)malloc(sizeof(st_edge));
newEdge->vertex = end;
newEdge->value = edgeValue;
newEdge->next = NULL;
*pCopyDes = newEdge;
}
}

图之Dijkstra算法的更多相关文章

  1. Dijkstra 算法,用于对有权图进行搜索,找出图中两点的最短距离

    Dijkstra 算法,用于对有权图进行搜索,找出图中两点的最短距离,既不是DFS搜索,也不是BFS搜索. 把Dijkstra 算法应用于无权图,或者所有边的权都相等的图,Dijkstra 算法等同于 ...

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

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

  3. 单源最短路径(1):Dijkstra 算法

    一:背景 Dijkstra 算法(中文名:迪杰斯特拉算法)是由荷兰计算机科学家 Edsger Wybe Dijkstra 提出.该算法常用于路由算法或者作为其他图算法的一个子模块.举例来说,如果图中的 ...

  4. Dijkstra算法(朴素实现、优先队列优化)

    Dijkstra算法只能求取边的权重为非负的图的最短路径,而Bellman-Ford算法可以求取边的权重为负的图的最短路径(但Bellman-Ford算法在图中存在负环的情况下,最短路径是不存在的(负 ...

  5. 理解最短路径-Dijkstra算法

    最短路径—Dijkstra算法和Floyd算法 透彻理解迪杰斯特拉算法 Dijkstra算法的使用条件:图中不存在负权边. ---------------------------有待验证------- ...

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

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

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

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

  8. C++编程练习(11)----“图的最短路径问题“(Dijkstra算法、Floyd算法)

    1.Dijkstra算法 求一个顶点到其它所有顶点的最短路径,是一种按路径长度递增的次序产生最短路径的算法. 算法思想: 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的 ...

  9. 数据结构与算法系列研究七——图、prim算法、dijkstra算法

    图.prim算法.dijkstra算法 1. 图的定义 图(Graph)可以简单表示为G=<V, E>,其中V称为顶点(vertex)集合,E称为边(edge)集合.图论中的图(graph ...

随机推荐

  1. [ python ] 学习目录大纲

    简易博客[html+css]练习 MySQL 练习题及答案 MySQL视图.触发器.函数.存储过程 MySQL 操作总结 Day41 - 异步IO.协程 Day39/40 - 线程的操作 Day36/ ...

  2. Python 内置装饰器

    内置的装饰器 ​ 内置的装饰器和普通的装饰器原理是一样的,只不过返回的不是函数,而是类对象,所以更难理解一些. @property ​ 在了解这个装饰器前,你需要知道在不使用装饰器怎么写一个属性. d ...

  3. JQuery中DOM事件合成用法

    jQuery有两个合成事件——hover()方法和toggle()方法 类似前面讲过的ready()方法,hover()方法和toggle()方法都属于jQuery自定义的方法. hover()方法: ...

  4. python dict交换key value值

    方法一: 使用dict.items()方式 dict_ori = {'A':1, 'B':2, 'C':3} dict_new = {value:key for key,value in dict_o ...

  5. 洛谷P1782 旅行商的背包

    传送门啦 这个题不用二进制优化的话根本不行,现学的二进制优化,调了一段时间终于A了,不容易.. 如果不懂二进制优化的话可以去看我那个博客 二进制优化多重背包入口 不想TLE,不要打memset,一定要 ...

  6. Linux基础 - tmux

    安装 yum install tmux 类似vim当中存在命令行模式以及编辑模式,从编辑模式进入命令行模式需要先按ESC键,在tmux当中进行操作也要先准备好"姿势"再操作,默认情 ...

  7. Codeforces 931D Peculiar apple-tree(dfs+思维)

    题目链接:http://codeforces.com/contest/931/problem/D 题目大意:给你一颗树,每个节点都会长苹果,然后每一秒钟,苹果往下滚一个.两个两个会抵消苹果.问最后在根 ...

  8. Luogu P4894 【GodFly求解法向量】

    个人感觉我的解法比官方题解好理解得多 因为是任意一个法向量嘛,不妨设$x=1$ 然后解一个二元一次方程就可以解决了 但是因为要求输出三个整数 代码 #include<iostream> # ...

  9. 20155225 2016-2017-2 《Java程序设计》第六周学习总结

    20155225 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 java的输入输出系统 在重新指定标准输入输出时不同: 重新指定标准输入为文档输入时,是这样 ...

  10. Winafl学习笔记

    最近在跟师傅们学习Winafl,也去搜集了一些资料,有了一些自己的理解,就此记录一下. Winafl是一个运行时插桩工具,可以提高crash的捕获率. 同时也有自己的遗传算法,可以根据代码覆盖程度进行 ...