迪杰斯特拉算法-寻找最短路径(有权/无权图)

前言:迪杰斯特拉算法寻找最短路径学习和实现笔记

什么是迪杰斯特拉算法-最短路径

迪杰斯特拉算法-手动寻找最短路径

为什么不能应用于负权值图

就比如如下图的情况,此时如果是正的有权图,那么找到的最短路径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;
}

posted @   zpchcbd  阅读(254)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示