迪杰斯特拉算法-寻找最短路径(有权/无权图)
前言:迪杰斯特拉算法寻找最短路径学习和实现笔记
什么是迪杰斯特拉算法-最短路径
迪杰斯特拉算法-手动寻找最短路径
为什么不能应用于负权值图
就比如如下图的情况,此时如果是正的有权图,那么找到的最短路径v0-v2,但是由于负权值图的存在(v1-v2的边权值为-5),这就导致了v0到v2顶点的最短路径就变成了v0-v1-v2
迪杰斯特拉算法-最短路径实现
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX 32767 #define OK 1 #define ERROR 0 typedef int ElemType; typedef int Status; typedef char VexType; typedef struct _Graph { int vexNum; int arcNum; int** arcs; char* vexs; }Graph, *PGraph; // 初始化graph Graph* initGraph(int vexNum) { Graph* pGraph = NULL; if (pGraph == NULL) { pGraph = (Graph*)malloc(sizeof(Graph)); memset(pGraph, 0, sizeof(Graph)); if (pGraph == NULL) return NULL; pGraph->vexNum = vexNum; pGraph->vexs = (char*)malloc(sizeof(pGraph->vexNum)); memset(pGraph->vexs, 0, sizeof(pGraph->vexNum)); pGraph->arcNum = 0; pGraph->arcs = (int**)malloc(sizeof(int*)* pGraph->vexNum); memset(pGraph->arcs, sizeof(int*)* pGraph->vexNum, 0); for (int i = 0; i < pGraph->vexNum; i++) { pGraph->arcs[i] = (int*)malloc(sizeof(int)* pGraph->vexNum); memset(pGraph->arcs[i], 0, sizeof(int)*pGraph->vexNum); } } return pGraph; } // 创建邻接矩阵 - 边 - 顶点 - 顶点 - 权值 Status createGraph(Graph** pGraph, char* vexs, int* arcs) { if (*pGraph == NULL) return ERROR; for (int i = 0; i<(*pGraph)->vexNum; i++) { *((*pGraph)->vexs + i) = *(vexs + i); for (int j = 0; j<(*pGraph)->vexNum; j++) { (*pGraph)->arcs[i][j] = *(arcs + i*((*pGraph)->vexNum) + j); printf("%d\t", (*pGraph)->arcs[i][j]); if ((*pGraph)->arcs[i][j] != 0 && (*pGraph)->arcs[i][j] != MAX) (*pGraph)->arcNum++; } printf("\n"); } (*pGraph)->arcNum /= 2; return OK; } // 深度优先遍历DFS Status DFS(Graph* pGraph, int* iVisitedArray, int visitedIndex) { if (pGraph == NULL) return ERROR; iVisitedArray[visitedIndex] = 1; printf("%c ", pGraph->vexs[visitedIndex]); for (int i = 0; i<pGraph->vexNum; i++) { if (pGraph->arcs[visitedIndex][i] > 0 && !iVisitedArray[i] && pGraph->arcs[visitedIndex][i] != MAX) DFS(pGraph, iVisitedArray, i); } return OK; } // 记录当前顶点的相关的路径权值 typedef struct _Edge{ char vex; int weight; }Edge; // 标识当前顶点是否为最短路径使用 typedef struct _VexSet{ int iFlag; }VexSet; // 标识顶点的最小路径 VexSet* initVexSet(Graph* pGraph) { VexSet* pVexSet = (VexSet*)malloc(sizeof(VexSet)* pGraph->vexNum); for (int i = 0;i<pGraph->vexNum;i++) pVexSet[i].iFlag = 0; return pVexSet; } // Edge的结构体用来存储当前顶点相邻顶点之间的边的权值 // 后面每次找到一个最小权值的边之后,会以对应的顶点去更新Edge结构体为后续循环继续使用 Edge* initEdge(Graph* pGraph, VexSet* pVexSet, int index) { Edge* pEdge = (Edge*)malloc(sizeof(Edge)*pGraph->vexNum); for (int i = 0; i<pGraph->vexNum; i++) { pEdge[i].vex = pGraph->vexs[index]; pEdge[i].weight = pGraph->arcs[index][i]; } // 默认第一个顶点和自己的距离最短,那么这个顶点的最短路径就是自己 pVexSet[index].iFlag = 1; return pEdge; } // 返回的是下一个要取得最小权值的顶点的索引 int getMinIndex(Graph* pGraph, Edge* pEdge, VexSet* pVexSet) { int index = 0; int iMin = MAX; for (int i = 0; i < pGraph->vexNum; i++) { if (pEdge[i].weight != 0 && pEdge[i].weight < iMin && pVexSet[i].iFlag == 0) { iMin = pEdge[i].weight; index = i; } } // 输出最短路径的边的两个顶点 printf("%c -- %c -- weight: %d \n", pEdge[index].vex, pGraph->vexs[index], pEdge[index].weight); return index; // 每次返回的都是edge中最小权值对应的索引 } int getMinWeight(Graph* pGraph, Edge* pEdge, VexSet* pVexSet) { int index = 0; int iMin = MAX; for (int i = 0; i < pGraph->vexNum; i++) { if (pEdge[i].weight != 0 && pEdge[i].weight < iMin && pVexSet[i].iFlag == 0) { iMin = pEdge[i].weight; index = i; } } return iMin; } // 测试从索引0开始进行寻找其他顶点之间的最短路径 void getDijkstra(Graph* pGraph, int index) { VexSet* pVexSet = initVexSet(pGraph); Edge* pEdge = initEdge(pGraph, pVexSet, index); int iMinIndex; int iMinWeight; // 循环次数为pGraph->vexNum-1次 for (int i = 0;i<pGraph->vexNum-1;i++) { // 获取Edge中当前顶点相邻的最小权值的顶点 iMinIndex = getMinIndex(pGraph, pEdge, pVexSet); iMinWeight = getMinWeight(pGraph, pEdge, pVexSet); // 设置顶点最小权值的标志位 pVexSet[iMinIndex].iFlag = 1; // 每次找完之后都需要更新一次pEdge,pEdge记录的永远是当前权值的最小值 for (int j = 0;j<pGraph->vexNum;j++) { if (pEdge[j].weight > pGraph->arcs[iMinIndex][j] && pGraph->arcs[iMinIndex][j] != 0) { pEdge[j].weight = iMinWeight + pGraph->arcs[iMinIndex][j]; pEdge[j].vex = pGraph->vexs[iMinIndex]; } } } } int main() { int initArcs[6][6] = { 0,1,12,MAX,MAX,MAX, MAX,0,9,3,MAX,MAX, MAX,MAX,0,MAX,5,MAX, MAX,MAX,4,0,13,15, MAX,MAX,MAX,MAX,0,4, MAX,MAX,MAX,MAX,MAX,0 }; char initVexs[7] = "123456"; Graph* pGraph = initGraph(6); createGraph(&pGraph, initVexs, (int*)initArcs); getDijkstra(pGraph, 0); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY