網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
前言
我們?cè)谏钪谐3C媾R對(duì)路徑選擇的決策問(wèn)題,這就要用到最短路徑的算法了。
對(duì)于我這種榆木腦袋,顯然迪杰斯特拉的這種算法有點(diǎn)高深。主要是我笨。
對(duì)于網(wǎng)圖來(lái)說(shuō),最短路徑,就是指兩個(gè)頂點(diǎn)之間經(jīng)過(guò)的邊上權(quán)值之和最小的路徑,并且我們稱路徑上的第一個(gè)頂點(diǎn)就是源點(diǎn),最后一個(gè)頂點(diǎn)式終點(diǎn)。
一、迪杰斯特拉(Dijkstra)算法是什么
迪杰斯特拉算法是一個(gè)按照路徑長(zhǎng)度遞增的次序產(chǎn)生最短路徑的算法。
二、實(shí)現(xiàn)步驟
1.算法思路
這里先采用鄰接表來(lái)遍歷。
在遍歷節(jié)點(diǎn)時(shí),找到未遍歷節(jié)點(diǎn)中權(quán)值最小的進(jìn)行遍歷,并且及時(shí)更新最短路徑長(zhǎng)度dist數(shù)組[]。
首先設(shè)置path[]數(shù)組代表路徑信息。 dist[] 表示最短路徑長(zhǎng)度。
int* path = (int*)malloc(sizeof(G.vexnum));
int* dist = (int*)malloc(sizeof(G.vexnum));
2.進(jìn)入主函數(shù)ShortestPath()
1.創(chuàng)建final數(shù)組并且初始化path[]、dist[]數(shù)組
final數(shù)組來(lái)表示是否完成對(duì)該節(jié)點(diǎn)的最短路徑求解。final[v]==1表示完成最短路徑搜素,反之final[vi]==0表示未完成。
在算法中只有在求得最短路徑后才會(huì)將final[vi]置為1,也可以簡(jiǎn)單理解為訪問(wèn)標(biāo)志數(shù)組。
path數(shù)組全體初始化為0。
final數(shù)組因?yàn)樽铋_始并沒(méi)有完成最短路徑求解,故置為0。
dist數(shù)組初始化為與vi相連的節(jié)點(diǎn)的權(quán)值,沒(méi)連就是INFINITY(65535)。
int* final = (int*)malloc(sizeof(int) * g.vexnum);
for (int i = 0; i < g.vexnum; i++) {
path[i] = 0;
final[i] = 0;
dist[i] = INFNITY;
}
ArcNode* p = g.vertexlist[vi].firstarc;
for (p; p != NULL; p = p->nextarc) {
dist[p->adjvex] = p->weight;
}
2.對(duì)于節(jié)點(diǎn)的初始化
在遍歷vi節(jié)點(diǎn)時(shí),vi到vi的路徑為0,vi到vi之間也不需要求路徑,故dist[vi]=0;final[vi]=1;
dist[vi] = 0;
final[vi] = 1;
肯定有人問(wèn),那path呢,path代表路徑信息,vi時(shí)源點(diǎn)自然就是0了,當(dāng)然初始化時(shí)也可以把path全初始化為-1,看個(gè)人習(xí)慣了。
3.進(jìn)入主循環(huán)
將對(duì)刨掉源點(diǎn)的其他節(jié)點(diǎn)進(jìn)行遍歷,故外循環(huán)次數(shù)為g.vexnum-1次。
再在dist數(shù)組中找到權(quán)值最小并且未完成最短路徑搜索的節(jié)點(diǎn),用k來(lái)表示該節(jié)點(diǎn)下標(biāo)。
其次找到最小權(quán)值k節(jié)點(diǎn)后,設(shè)置final[k]=1,再對(duì)k節(jié)點(diǎn)進(jìn)行遍歷,更新dist和path數(shù)組。
更新方法:若與k節(jié)點(diǎn)相連的節(jié)點(diǎn)未完成最短路徑搜索并且k節(jié)點(diǎn)權(quán)值+該節(jié)點(diǎn)權(quán)值小于dist數(shù)組中的源點(diǎn)到該節(jié)點(diǎn)的最短路徑,那么將更新dist數(shù)組中到該節(jié)點(diǎn)的最短路徑,并且更新path數(shù)組,到該節(jié)點(diǎn)的前驅(qū)為k節(jié)點(diǎn)。
int k;
for (int v = 1; v < g.vexnum; v++) {
int min = INFNITY;
for (int w = 0; w < g.vexnum; w++) {
if (!final[w] && dist[w] < min) {
k = w;
min = dist[w];
}
}
final[k] = 1;
ArcNode* p = g.vertexlist[k].firstarc;
while (p != NULL) {
if (!final[p->adjvex] && (p->weight + min) < dist[p->adjvex]) {
dist[p->adjvex] = min + p->weight;
path[p->adjvex] = k;
}
p = p->nextarc;
}
}
三、全部代碼(鄰接表下)
void ShortestPath(AdjList g, int vi, int* path, int* dist) {
int* final = (int*)malloc(sizeof(int) * g.vexnum);
for (int i = 0; i < g.vexnum; i++) {
path[i] = 0;
final[i] = 0;
dist[i] = INFNITY;
}
ArcNode* p = g.vertexlist[vi].firstarc;
for (p; p != NULL; p = p->nextarc) {
dist[p->adjvex] = p->weight;
}
dist[vi] = 0;
final[vi] = 1;
int k;
for (int v = 1; v < g.vexnum; v++) {
int min = INFNITY;
for (int w = 0; w < g.vexnum; w++) {
if (!final[w] && dist[w] < min) {
k = w;
min = dist[w];
}
}
final[k] = 1;
ArcNode* p = g.vertexlist[k].firstarc;
while (p != NULL) {
if (!final[p->adjvex] && (p->weight + min) < dist[p->adjvex]) {
dist[p->adjvex] = min + p->weight;
path[p->adjvex] = k;
}
p = p->nextarc;
}
}
free(final);
return;
}
四、全部代碼(鄰接矩陣下)
思路大同小異,在初始化時(shí)有些不同,其他很相像。
void ShortestPath(AdjMatrix g, int vi, int* path, int* dist) {
int* final = (int*)malloc(sizeof(int) * g.vexnum);
for (int i = 0; i < g.vexnum; i++) {
path[i] = 0;
final[i] = 0;
dist[i] = g.arc[vi][i];
}
dist[vi] = 0;
final[vi] = 1;
int k;
for (int v = 1; v < g.vexnum; v++) {
int min = INFNITY;
for (int w = 0; w < g.vexnum; w++) {
if (!final[w] && dist[w] < min) {
k = w;
min = dist[w];
}
}
final[k] = 1;
ArcNode* p = g.vertexlist[k].firstarc;
for (int w = 0; w < g.vexnum; w++) {
if (!final[w] && (min+g.arc[k][w])<dist[w]) {
dist[w]=min+g.arc[k][w];
path[w]=k;
}
}
}
free(final);
return;
}
五、測(cè)試代碼(鄰接表下)
這里就測(cè)試一個(gè)鄰接表下的。
自己花了個(gè)圖
因?yàn)槲业倪叡斫⒌臅r(shí)候A是第一個(gè),自然A就是源點(diǎn)。
結(jié)果如下
很完美。
總結(jié)
很顯然這個(gè)算法的時(shí)間復(fù)雜度是O(n2),如果要知道任意頂點(diǎn)到其余所有頂點(diǎn)的最短路徑,那么就可以對(duì)每一個(gè)頂點(diǎn)當(dāng)作源點(diǎn)進(jìn)行一次迪杰斯特拉算法。這時(shí)候后整個(gè)算法的時(shí)間復(fù)雜度也就成了O(n3)。這個(gè)和弗洛伊德算法的時(shí)間復(fù)雜度一樣,但弗洛伊德算法那是相當(dāng)?shù)膬?yōu)雅。
原文鏈接:https://blog.csdn.net/qq_45400167/article/details/125982074
相關(guān)推薦
- 2022-02-14 Uncaught TypeError: Failed to execute ‘a(chǎn)ppendChild
- 2022-07-10 詳解transition 被動(dòng)動(dòng)畫
- 2022-11-01 如何使用Kubernetes自定義資源(CRD)詳解_云其它
- 2022-07-13 Dos攻擊Tomcat導(dǎo)致coredump問(wèn)題分析
- 2022-07-03 python使用pandas讀xlsx文件的實(shí)現(xiàn)_python
- 2022-12-15 深入了解Golang中的格式化輸出_Golang
- 2022-03-30 ASP.NET?Core使用JWT自定義角色并實(shí)現(xiàn)策略授權(quán)需要的接口_實(shí)用技巧
- 2022-06-28 深入解析docker文件分層原理_docker
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支