/* Dijkstra 算法: 其实该算法和prim算法相似,不同的仅仅是更新那一块 我们这里仍然需要用到一个标记数组flag,用于记录顶点是否已被访问,一个路径数组dist,用于记录 目前到达各顶点的距离,此外我们还需要一个前置顶点数组prevs,用于存储路径*/#define MAXSIZE 100 //数组最大值#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>typedef struct Graph { int Vertex[MAXSIZE]; int Edge[MAXSIZE][MAXSIZE]; int numV, numE;//顶点、边数量}adjMatrix;void dijkstra(adjMatrix *G, int start) { int flag[MAXSIZE];//标记数组 //int preV=0;//设置preV最开始为0 int dist[MAXSIZE];//可到达顶点的距离数据 int prevs[MAXSIZE];//存储每个顶点的前驱,也就是存储路径 int k = start; for (int i = 0; i < G->numV; i++) { dist[i] = G->Edge[start][i];//初始化start到各顶点的距离 prevs[i] = 0;//初始化 flag[i] = 0; } flag[0] = 1;//传入的顶点设为已访问 for (int i = 0; i < G->numV; i++) {//共进行G->numV次循环 if (start == i)//是本身,不做操作 continue; int min = 32767; //找目前能到达的权值最小顶点 for (int j = 0; j < G->numV; j++) { if (!flag[j] && dist[j] < min) {//dist不为0代表未访问过 min = dist[j]; k = j; } } flag[k] = 1; //当我们加入新顶点时,我们要判断加入新顶点后是否路径会缩短,如果有这种情况,就要更新dist for (int m = 0; m < G->numV; m++) { if (!flag[m] && dist[m] > G->Edge[k][m] + dist[k]) {//当前 记录的从源点到k的距离 大于 加入k后的距离,进行更新!! dist[m] = G->Edge[k][m] + dist[k]; prevs[m] = k;//一旦发生更换将m处的值设为k,代表由k处的顶点指向m处的顶点目前最近,即k是m的前驱 } } } for (int i = 0; i < G->numV; i++) { i == start ? printf("%d ", 0) : printf("%d ", G->Vertex[prevs[i]]-48); } printf("\n"); for (int i = 0; i < G->numV; i++) { printf("%d ", dist[i]); }}int main() { void createGraphFromFile(adjMatrix *); void dispGraph(adjMatrix *G); adjMatrix *G = (adjMatrix *)malloc(sizeof(adjMatrix)); createGraphFromFile(G); dispGraph(G); dijkstra(G, 0); return 0;}
/* Dijkstra 算法(图用邻接表实现): 其实该算法和prim算法相似,不同的仅仅是更新那一块 我们这里仍然需要用到一个标记数组flag,用于记录顶点是否已被访问,一个路径数组dist,用于记录 目前到达各顶点的距离,此外我们还需要一个前置顶点数组prevs,用于存储路径*/#define MAXSIZE 100 //数组最大值#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#define MAXSIZE 100#define TYPE inttypedef struct EdgeNode {//边表结点 int index;//该边所指向的顶点的位置 int weight;//权值 EdgeNode *next;//下一个邻接边}EdgeNode;typedef struct VertexNode {//顶点表节点 char info;//顶点信息 EdgeNode *firstEdge;//指向第一条依附该顶点的边的指针}VertexNode, Adjlist[MAXSIZE];typedef struct { Adjlist adjlist;//顶点数组 int numE, numV;//边数、顶点数}ALGraph;int getWeiFromAtoB(ALGraph *G, int a, int b) {//在图中获取a 到 b的距离(权值) for (EdgeNode *p = G->adjlist[a].firstEdge; p; p = p->next) { if (p->index == b) {//有直接连接,返回权值 return p->weight; } } return 32767;//若没有直接连接,返回最大值}void dijkstra(ALGraph *G, int start) { int flag[100];//标记数组 int preV=0;//设置preV最开始为0 int dist[100];//可到达顶点的距离数据 int prevs[100];//存储每个顶点的前驱,也就是存储路径 int k = start; for (int i = 0; i < G->numV; i++) { dist[i] = 32767;//把所有值设为无穷 } for (EdgeNode *p = G->adjlist[start].firstEdge; p; p = p->next) { dist[p->index] = p->weight;//把当前传入顶点的所有连接顶点的边的权值存入 } for (int i = 0; i < G->numV;i++) { prevs[i] = 0;//初始化 flag[i] = 0; } flag[0] = 1;//传入顶点设为已访问 for (int i = 0; i < G->numV;i++) {//共进行G->numV次循环 if (start == i)//是本身,不做操作 continue; int min = 32767; //找目前能到达的权值最小顶点 for (int j = 0; j < G->numV;j++) { if (!flag[j]&&dist[j]<min) {//dist不为0代表未访问过 min = dist[j]; k = j; } } flag[k]=1; //当我们加入新顶点时,我们要判断加入新顶点后是否路径会缩短,如果有这种情况,就要更新dist for (int m = 0; m < G->numV; m++) { int weight = getWeiFromAtoB(G, k, m); if (!flag[m]&&dist[m]> weight +dist[k]) {//当前 记录的从源点到k的距离 大于 加入k后的距离,进行更新!! dist[m] = weight + dist[k]; prevs[m] = k;//一旦发生更换将m处的值设为k,代表由k处的顶点指向m处的顶点目前最近,即k是m的前驱 } } } for (int i = 0; i < G->numV;i++) { printf("%c ",G->adjlist[prevs[i]].info); }}int main() { ALGraph *G = (ALGraph *)malloc(sizeof(ALGraph *)); void createGraphInFile(ALGraph *); void dispGraph(ALGraph *); createGraphInFile(G);//创建图 dispGraph(G); dijkstra(G, 0); return 0;}