算法思想:(单源最短路径)

  • 1个点到所有其他点的最短路径
  • 查找顶点到其他顶点的最短路径,无法到达的记为+∞,找到最小的,就找到了最短路径的顶点
  • 查看上一轮找到的最小点到达其他点的最小值,找到最短路径的顶点。
  • 以此类推
  • trivial relax:无穷大 ==> 具体数字
  • non-trival relax:具体数字 ==> 具体数

参考:https://www.bilibili.com/video/av36886088


运行效果:

step = 1, minw = 0, pacost[0] = 0.00
trival relax: pacost[1] = inf ==> 1.00
trival relax: pacost[3] = inf ==> 2.00 step = 2, minw = 1, pacost[1] = 1.00
trival relax: pacost[2] = inf ==> 4.00 step = 3, minw = 3, pacost[3] = 2.00
trival relax: pacost[2] = 4.00 ==> 3.00 step = 4, minw = 2, pacost[2] = 3.00 visited: {1, 1, 1, 1}
parent: {-1, 0, 3, 0}
pacost: {0.00, 1.00, 3.00, 2.00}

代码:

Dijkstra.c

#include <stdio.h>
#include <stdlib.h> #include "WeGraph.h" void DijkstraPrim(Graph g, int nV, int nE, Vertex src, char alg); int main(){
Graph g = newGraph(4);
Edge e = newEdge(0, 1, 1);
insertEdge(e, g); e = newEdge(1, 2, 3);
insertEdge(e, g); e = newEdge(2, 3, 1);
insertEdge(e, g); e = newEdge(3, 0, 2);
insertEdge(e, g); DijkstraPrim(g, 4, 4, 0, 'd'); return 0;
} int *mallocArray(int numV) {
int *array = malloc(numV * sizeof(int));// l
if (array == NULL) { // o
fprintf(stderr, "Out of memory\n"); // c
exit(1); // a
} // l
int i; // f
for (i=0; i<numV; i++) { // u
array[i] = UNVISITED; // n
} // c
return array; // t
} float *mallocFArray(int numV) {
float *array = malloc(numV * sizeof(float));// l
if (array == NULL) { // o
fprintf(stderr, "Out of memory\n"); // c
exit(1); // a
} // l
int i; // f
for (i=0; i<numV; i++) { // u
array[i] = MAXWEIGHT; // n
} // c
return array; // t
} void showArray(char *desc, int *array, int numV) {
int i; // l
printf("%s: {", desc); // o
for (i=0; i<numV; i++) { // c
printf("%d", array[i]); // a
if (i <= numV-2) { // l
printf(", "); // f
} // u
} // n
printf("}\n"); // c
return; // t
} void showFArray(char *desc, float *array, int numV) {
int i; // l
printf("%s: {", desc); // o
for (i=0; i<numV; i++) { // c
printf("%0.2f", array[i]); // a
if (i <= numV-2) { // l
printf(", "); // f
} // u
} // n
printf("}\n"); // c
return; // t
} void DijkstraPrim(Graph g, int nV, int nE, Vertex src, char alg) {
// the last parameter arg is set by main, and is:
// 'd' for Dijkstra or
// 'p' for Prim int *visited = mallocArray(nV); // initialised to UNVISITED
int *parent = mallocArray(nV); // initialised to UNVISITED
float *pacost = mallocFArray(nV); // floats: initialised to INFINITY pacost[src] = 0.0;
for (int step = 1; step <= nV; step++) { printf ("\nstep = %d, ", step); Vertex minw = -1;
for (Vertex w = 0; w < nV; w++) { // find minimum cost vertex
if ((visited[w] == UNVISITED) &&
(minw == -1 || pacost[w] < pacost[minw])) {
minw = w;
}
} printf ("minw = %d, ", minw);
printf ("pacost[%d] = %0.2f\n", minw, pacost[minw]); visited[minw] = VISITED; for (Vertex w = 0; w < nV; w++) { //
Weight minCost = getWeight(g, minw, w);// if minw == w, minCost = NOWEIGHT
// minCost is cost of the minimum crossing edge
if (minCost != NOWEIGHT) {
if (alg == 'd') { // if DIJKSTRA ...
minCost = minCost + pacost[minw];// add in the path cost
}
if ((visited[w] != VISITED) &&
(minCost < pacost[w])) {
printf (" trival relax: pacost[%d] = %0.2f ", w, pacost[w]); pacost[w] = minCost;
parent[w] = minw; printf ("==> %0.2f\n", pacost[w]);
}
}
} } printf("\n"); showArray("visited", visited, nV);
showArray("parent", parent, nV);
showFArray("pacost", pacost, nV);
free(visited);
free(parent);
free(pacost);
return;
}

WeGraph.c

// WeGraph.c: an adjacency matrix implementation of a weighted graph
#include <stdio.h>
#include <stdlib.h>
#include "WeGraph.h" struct graphRep {
int nV; // #vertices
int nE; // #edges
Weight **edges; // matrix of weights
}; Graph newGraph(int numVertices) {
Graph g = NULL;
if (numVertices < 0) {
fprintf(stderr, "newgraph: invalid number of vertices\n");
}
else {
g = malloc(sizeof(struct graphRep));
if (g == NULL) {
fprintf(stderr, "newGraph: out of memory\n");
exit(1);
}
g->edges = malloc(numVertices * sizeof(int *));
if (g->edges == NULL) {
fprintf(stderr, "newGraph: out of memory\n");
exit(1);
}
int v;
for (v = 0; v < numVertices; v++) {
g->edges[v] = malloc(numVertices * sizeof(int));
if (g->edges[v] == NULL) {
fprintf(stderr, "newGraph: out of memory\n");
exit(1);
}
int j;
for (j = 0; j < numVertices; j++) {
g->edges[v][j] = NOWEIGHT;
}
}
g->nV = numVertices;
g->nE = 0;
}
return g;
} void freeGraph(Graph g) {
if (g != NULL) {
int i;
for (i = 0; i < g->nV; i++) {
free(g->edges[i]); // free the mallocs for each row ...
}
free(g->edges); // now the malloc for the edges array ...
free(g); // now the malloc for the graph rep
}
return;
} static int validV(Graph g, Vertex v) { // checks if v is in graph
return (v >= 0 && v < g->nV);
} Edge newEdge(Vertex v, Vertex w, Weight x) { // create an edge from v to w
Edge e = {v, w, x};
return e;
} void showEdge(Edge e) { // print an edge and its weight
printf("%d-%d: %.2f", e.v, e.w, e.x);
return;
} int isEdge(Edge e, Graph g) { // 0 if not found, else 1; also fill in wgt
int found = 0;
if (g != NULL) {
if (g->edges[e.v][e.w] != NOWEIGHT) {
found = 1;
}
}
return found;
} Edge getEdge(Vertex v, Vertex w, Graph g) {
Edge e = {0, 0, 0.0};
if (validV(g, v) || validV(g, w)) {
e.v = v;
e.w = w;
e.x = g->edges[v][w];
}
return e;
} int cmpEdge(Edge e1, Edge e2) { // comparison based on edge weight
int retval = 0;
if (e1.x < e2.x) {
retval = -1;
}
else if (e1.x > e2.x) {
retval = 1;
}
return retval;
} void insertEdge(Edge e, Graph g) { // insert an edge into a graph
if (g == NULL) {
fprintf(stderr, "insertEdge: graph not initialised\n");
}
else {
if (!validV(g, e.v) || !validV(g, e.w)) {
fprintf(stderr, "insertEdge: invalid vertices %d-%d\n", e.v, e.w);
}
else {
if (!isEdge(e, g)) { // increment nE only if it is new
g->nE++;
}
g->edges[e.v][e.w] = e.x;
g->edges[e.w][e.v] = e.x;
}
}
return;
} void removeEdge(Edge e, Graph g) { // remove an edge from a graph
if (g == NULL) {
fprintf(stderr, "removeEdge: graph not initialised\n");
}
else {
if (!validV(g, e.v) || !validV(g, e.w)) {
fprintf(stderr, "removeEdge: invalid vertices\n");
}
else {
if (isEdge(e, g) == NOWEIGHT) { // is edge there?
g->edges[e.v][e.w] = NOWEIGHT;
g->edges[e.w][e.v] = NOWEIGHT;
g->nE--;
}
}
}
return;
} Weight getWeight(Graph g, Vertex v1, Vertex v2) { // get Weight: NOWEIGHT if not existing
Edge e = {v1, v2}; // not required, but for consistency
Weight retval = 0.0; if (g == NULL) {
fprintf(stderr, "getWeight: graph not initialised\n");
}
else {
if (!validV(g, e.v) || !validV(g, e.w)) {
fprintf(stderr, "getWeight: invalid vertices\n");
}
else {
retval = g->edges[e.v][e.w];
}
}
return retval;
} void showGraph(Graph g) { // print a graph
if (g == NULL) {
printf("NULL graph\n");
}
else {
printf("V=%d, E=%d\n", g->nV, g->nE);
int i;
for (i = 0; i < g->nV; i++) {
int nshown = 0;
int j;
for (j = 0; j < g->nV; j++) {
if (g->edges[i][j] != NOWEIGHT) {
printf("%d %d:%.2f ", i, j, g->edges[i][j]);
nshown++;
}
}
if (nshown > 0) {
printf("\n");
}
}
}
return;
}

WeGraph.h

// WeGraph.h: an interface for a weighted graph ADT
#include <math.h> typedef float Weight; // define a WEIGHT
#define NOWEIGHT -1.0
#define MAXWEIGHT INFINITY typedef int Vertex; // define a VERTEX
#define UNVISITED -1
#define VISITED 1 typedef struct {
Vertex v;
Vertex w;
Weight x;
} Edge; typedef struct graphRep *Graph; // define a GRAPH Graph newGraph(int);
void freeGraph(Graph);
void showGraph(Graph); void insertEdge(Edge, Graph);
void removeEdge(Edge, Graph);
void showEdge(Edge);
int isEdge(Edge, Graph);
Edge newEdge(Vertex, Vertex, Weight);
Edge getEdge(Vertex, Vertex, Graph);
int cmpEdge(Edge, Edge); Weight getWeight(Graph, Vertex, Vertex);

【428】Dijkstra 算法的更多相关文章

  1. 求两点之间最短路径-Dijkstra算法

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

  2. Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解

    /* Dijkstra算法用优先队列来实现,实现了每一条边最多遍历一次. 要知道,我们从队列头部找到的都是到 已经"建好树"的最短距离以及该节点编号, 并由该节点去更新 树根 到其 ...

  3. 关于dijkstra算法的一点理解

    最近在准备ccf,各种补算法,图的算法基本差不多看了一遍.今天看的是Dijkstra算法,这个算法有点难理解,如果不深入想的话想要搞明白还是不容易的.弄了一个晚自习,先看书大致明白了原理,就根据书上的 ...

  4. 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)

    关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...

  5. Dijkstra算法(二)之 C++详解

    本章是迪杰斯特拉算法的C++实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法图解 3. 迪杰斯特拉算法的代码说明 4. 迪杰斯特拉算法的源码 转载请注明出处:http://www.cnbl ...

  6. Dijkstra算法(一)之 C语言详解

    本章介绍迪杰斯特拉算法.和以往一样,本文会先对迪杰斯特拉算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法 ...

  7. 最短路问题Dijkstra算法

    Dijkstra算法可以解决源点到任意点的最短距离并输出最短路径 准备: 建立一个距离数组d[ n ],记录每个点到源点的距离是多少 建立一个访问数组v[ n ],记录每个点是否被访问到 建立一个祖先 ...

  8. dijkstra算法求最短路

    艾兹格·W·迪科斯彻 (Edsger Wybe Dijkstra,1930年5月11日~2002年8月6日)荷兰人. 计算机科学家,毕业就职于荷兰Leiden大学,早年钻研物理及数学,而后转为计算学. ...

  9. 数据结构之Dijkstra算法

    基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求 ...

  10. ACM: HDU 1869 六度分离-Dijkstra算法

    HDU 1869六度分离 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Descri ...

随机推荐

  1. Go语言 - 数组 | 多维数组

    Array 数组是同一种数据类型元素的集合. 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化. 1.数组 在定义阶段,长度和类型就固定了,以后不能更改 2.长度也是数组 ...

  2. springboot框架笔记

    01.spring data是一个开源的框架,在这个开源的框架中spring  data  api只是其中的一个模块,只需要编写一个接口继承一个类就行了. 02.spring boot框架底层好像将所 ...

  3. C# mysql 处理 事务 回滚 提交

    MySqlConnection myCon; void iniMysql() { //连接数据库 myCon = new MySqlConnection("server=127.0.0.1; ...

  4. PHP命令行执行文件或代码

    Linux环境 1.执行代码 php -r "echo 'hello';" (注意加分号,与PHP文件一样) 2.执行文件 php -f  文件所在路径(/var/www/xxx. ...

  5. mock模拟后台数据

    import Mock from 'mockjs' const Random = Mock.Random // 获取random对象,随机生成各种数据,具体请翻阅文档 const domain = ' ...

  6. 解决Cannot find config.m4 Make sure that you run '/home/php/bin/phpize' in the top level source directory of the module

    oot@DK:/home/daokr/downfile/php-7.0.0/ext/mysqlnd# /home/php/bin/phpizeCannot find config.m4. Make s ...

  7. 飞扬的小鸟 DP

    飞扬的小鸟 DP 细节有点恶心的DP,设\(f[i][j]\)表示横坐标为\(i\)(从\(0\)开始)高度为\(j\)时,屏幕点击的最小次数为\(f[i][j]\),转移便很好写了,这里要注意枚举当 ...

  8. 繁繁的数字 背包DP

    繁繁的数字 背包DP 问一个数\(n\)有多少种二进制分解方案数 \(n\le 10^5\) 如7有7=4+2+1=4+1+1+1=2+2+2+1=2+2+1+1+1=2+1+1+1+1+1=1+1+ ...

  9. P4425 【[HNOI/AHOI2018]转盘】

    颂魔眼中的一眼题我大湖南竟无一人\(AC\) 首先我们考虑一个性质:我们肯定存在一种最优解,满足从某个点出发,一直往前走,不停下来. 证明:我们假设存在一种最优解,是在\(t_i\)的时候到达\(a\ ...

  10. ZR#990

    ZR#990 解法: 首先,一个 $ k $ 进制的数的末尾 $ 0 $ 的个数可以这么判断 while(x) { x /= k; cnt++;//cnt为0的个数 } 因为这道题的 $ 0 $ 的个 ...