數據結構 —— Dijkstra算法

數據結構 —— Dijkstra算法

  • Dijkstra算法
  • 劃分集合
  • 模擬過程
  • 打印路徑

在上次的博客中,我們解決了使用最小的邊讓各個頂點連通(最小生成樹
在這里插入圖片描述這次我們要解決的問題是現在有一個圖,我們要找到一條路,使得從一個頂點到另一個頂點路徑權值之和最小(比如:找到從小潮到胖迪最短的一條路徑):
在這里插入圖片描述
我們可以看出來,小潮->小傲->胖迪這條路徑是最短的。
在這里插入圖片描述
而我們今天學的算法,Dijkstra,就是完成這樣的工作的:

Dijkstra算法

Dijkstra算法是一種用于尋找圖中兩個節點之間的最短路徑的算法,由荷蘭計算機科學家Edsger W. Dijkstra于1956年發明。該算法的基本思想是使用貪心策略,從起始節點開始,逐步擴展到距離它最近的未訪問過的節點,直到目標節點被訪問。

以下是Dijkstra算法的基本步驟:

  1. 初始化將起點到所有其他節點的距離設為無窮大(表示還未計算),除了起點到自身的距離為0。創建一個空的已訪問節點集合和一個包含所有節點的未訪問節點集合。
  1. 從未訪問節點集合中選擇距離起點最近的節點,將其標記為已訪問,并更新其鄰接節點的距離如果某個鄰接節點的距離通過當前節點更短,則更新該鄰接節點的距離
  1. 重復步驟2,直到找到目標節點或未訪問節點集合為空。
  1. 如果找到了目標節點,則返回從起點到目標節點的最短路徑;否則,說明起點和目標節點之間不存在路徑。

需要注意的是,Dijkstra算法只適用于沒有負權重邊的圖,因為負權重邊會導致算法無法正確地確定最短路徑。此外,Dijkstra算法的時間復雜度為O(ElogV),其中E表示邊的數量,V表示節點的數量。在實際應用中,可以使用優先隊列等數據結構來優化算法的時間復雜度。

我們將上面的圖改造復雜一點,這樣可以看出Dijkstra算法的高效:
在這里插入圖片描述

void TestGraph2(){string a[] = {"海皇","高斯","小傲","小潮","胖迪","小楊","皖皖"};Graph<string, int,INT_MAX, false> g1(a, sizeof(a)/sizeof(a[0]));g1.AddEdge("小潮", "小傲", 30);g1.AddEdge("小潮", "高斯", 83);g1.AddEdge("小潮", "海皇", 34);g1.AddEdge("胖迪", "海皇", 78);g1.AddEdge("胖迪", "小傲", 76);g1.AddEdge("小楊", "皖皖", 54);g1.AddEdge("小楊", "高斯", 48);g1.AddEdge("高斯", "皖皖", 55);g1.AddEdge("胖迪", "高斯", 70);g1.AddEdge("小傲", "海皇", 3);g1.Print();cout << endl;}

在這里插入圖片描述

劃分集合

Dijkstra算法中,提到我們要劃分集合一個是訪問過的集合,一個是沒有被訪問過的集合,假設我們從小潮開始:
在這里插入圖片描述
我們可以用一個bool的數組,訪問過了的標記為true,沒有為false。
在這里插入圖片描述假設我們要從小潮到胖迪,我們要計算路徑之和,我們還需要一個數組存放到各個頂點邊的權值:

在這里插入圖片描述同時,如果我們想打印路徑出來,我們還要一個數組存放路徑(這里有點像并查集里面的操作)
在這里插入圖片描述

模擬過程

假設我們從小潮開始,各個數組情況如下:
在這里插入圖片描述

現在,掃描跟小潮相連的邊,最小的權值相關結點標記:
在這里插入圖片描述

現在我們從小傲出發,發現海皇近,跳到海皇,發現總路徑之和為33,比原來34小,故更新,并標記:

在這里插入圖片描述
我們代碼實現一下:

    void Dijkstra(const V& srci, vector<W>& dest, vector<int>& parentPath ){// 將源節點轉換為其在頂點列表中的索引int srcIndex = FindSrci(srci);// 初始化parentPath向量,用于記錄最短路徑上的前驅節點,初始值為-1表示未訪問parentPath.resize(_vertex.size(), -1);// 初始化dest向量,用于記錄從源節點到每個節點的最小距離,初始值為最大權重MAX_Wdest.resize(_vertex.size(), MAX_W);// 給源節點賦值為0,表示從源節點到自身距離為0dest[srcIndex] = W();// 初始化一個布爾型向量,用于記錄每個節點是否已被訪問,初始值為falsevector<bool> isVisted;isVisted.resize(_vertex.size(), false);// 主循環,迭代次數為頂點數for (size_t i = 0; i < _vertex.size(); i++){// 初始化最小距離為最大權重MAX_WW min = MAX_W;size_t u = srcIndex;// 尋找未被訪問且具有最小dest值的節點ufor (size_t j = 0; j < _vertex.size(); j++){if (isVisted[j] == false && dest[j] < min){min = dest[j];u = j;}}// 標記節點u為已訪問isVisted[u] = true;// 對節點u的所有鄰居進行松弛操作for (size_t i = 0; i < _vertex.size(); i++){// 只處理未被訪問的鄰居,并且存在從u到i的邊(_matrix[u][i] != MAX_W)if (isVisted[i] == false && _matrix[u][i] != MAX_W&& dest[u] + _matrix[u][i] < dest[i]){// 更新從源節點到節點i的最小距離dest[i] = dest[u] + _matrix[u][i];// 更新節點i的前驅節點為uparentPath[i] = u;}}}}

在這里插入圖片描述

打印路徑

打印路徑記得一點,最后我們要逆置一下:

    // 打印從源節點到所有其他節點的最短路徑void PrintShortestPath(const V& src, const vector<W>& dist, const vector<int>& parentPath){// 將源節點轉換為其在頂點列表中的索引size_t srcIndex = FindSrci(src);// 遍歷所有頂點for (size_t i = 0; i < _vertex.size(); i++){// 跳過源節點本身if (i == srcIndex)continue;// 創建一個vector,用于存儲從目標節點到源節點的路徑vector<int> path;// 當前處理的節點初始化為目標節點size_t current = i;// 從目標節點出發,回溯到源節點,構建路徑while (current != srcIndex){// 將當前節點添加到路徑vector中path.push_back(current);// 將當前節點設置為其前驅節點,繼續回溯current = parentPath[current];}// 最后將源節點添加到路徑vector中path.push_back(srcIndex);// 翻轉路徑vector,使得路徑順序從源節點到目標節點reverse(path.begin(), path.end());// 輸出路徑和對應的最短距離for (auto node : path){// 輸出路徑中的每個節點cout << _vertex[node] << "->";}// 輸出從源節點到目標節點的最短距離cout << dist[i] << endl;}}

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43845.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43845.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43845.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

對比學習和多模態任務

1. 對比學習 對比學習&#xff08;Contrastive Learning&#xff09;是一種自監督學習的方法&#xff0c;旨在通過比較數據表示空間中的不同樣本來學習有用的特征表示。其核心思想是通過最大化同類樣本之間的相似性&#xff08;或降低它們之間的距離&#xff09;&#xff0c;同…

【Linux】網絡新兵連

歡迎來到 破曉的歷程的 博客 ??不負時光&#xff0c;不負己?? 引言 在上一篇博客中&#xff0c;我們簡單的介紹了一些Linux網絡一些比較基本的概念。本篇博客我們將開始正式學習Linux網絡套接字的內容&#xff0c;那么我們開始吧&#xff01; 1.網絡中的地址管理 大家一…

GraphRAG——一個基于圖的檢索增強生成的開源項目【送源碼】

GraphRAG 最近幾天&#xff0c;微軟團隊開源了GraphRAG&#xff0c;這是一種基于圖&#xff08;Graph&#xff09;的檢索增強生成方法。 先說說RAG吧&#xff0c;檢索增強生成&#xff0c;相當于是從一個給定好的知識庫中進行檢索&#xff0c;接入LLM模型&#xff0c;讓模型生…

(十六)視圖變換 正交投影 透視投影

視圖變換 代碼實驗 #include <glad/glad.h>//glad必須在glfw頭文件之前包含 #include <GLFW/glfw3.h> #include <iostream> #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h"//GLM #include <glm/glm.hpp> #include <glm/gtc/m…

C++初探究(2)

引用 對于一個常量&#xff0c;想要將其進行引用&#xff0c;則使用普通的引用相當于權限擴大&#xff08;常量為只讀&#xff0c;但此處的引用參數為可讀可寫&#xff09;&#xff0c;C編譯器會報錯. 例如&#xff1a; const int a 10;int& ra a;//權限放大&#xff0…

邏輯回歸不是回歸嗎?那為什么叫回歸?

RNN 邏輯回歸不是回歸嗎&#xff1f;那為什么叫回歸&#xff1f;邏輯回歸的基本原理邏輯函數&#xff08;Sigmoid函數&#xff09;二元分類 為什么叫做“回歸”&#xff1f;邏輯回歸的應用場景總結 邏輯回歸不是回歸嗎&#xff1f;那為什么叫回歸&#xff1f; 邏輯回歸&#x…

Python大數據分析——決策樹和隨機森林

Python大數據分析——決策樹和隨機森林 決策樹決策樹節點字段的選擇信息熵條件熵信息增益信息增益率 基尼指數條件基尼指數基尼指數增益 決策樹函數 隨機森林函數 決策樹 圖中的決策樹呈現自頂向下的生長過程&#xff0c;深色的橢圓表示樹的根節點&#xff1b;淺色的橢圓表示樹…

Java項目:基于SSM框架實現的農家樂信息管理平臺含前后臺【ssm+B/S架構+源碼+數據庫+答辯PPT+開題報告+畢業論文】

一、項目簡介 本項目是一套基于SSM框架實現的農家樂信息管理平臺 包含&#xff1a;項目源碼、數據庫腳本等&#xff0c;該項目附帶全部源碼可作為畢設使用。 項目都經過嚴格調試&#xff0c;eclipse或者idea 確保可以運行&#xff01; 該系統功能完善、界面美觀、操作簡單、功…

招投標信息采集系統:讓您的企業始終站在行業前沿

一、為何招投標信息如此關鍵&#xff1f; 在經濟全球化的大背景下&#xff0c;招投標活動日益頻繁&#xff0c;成為企業獲取項目、拓展市場的主流方式之一。招投標信息采集&#xff0c;作為企業戰略決策的前置環節&#xff0c;其重要性不言而喻。它不僅關乎企業能否第一時間發…

WPF 初識依賴屬性

依賴屬性的意義和作用 核心模塊內存共享&#xff0c;節省空間數據綁定、樣式、模板、動畫。。。。如果沒有依賴屬性&#xff0c;這個框架就是一個控件框架 相當于Winform 依賴屬性的基本定義 基本過程&#xff1a;聲明、注冊、包裝 在需要寫依賴屬性的類中&#xff0c;繼承…

快速將一個網址打包成一個exe可執行文件

一、電腦需要node環境 如果沒有下面有安裝教程&#xff1a; node.js安裝及環境配置超詳細教程【Windows系統安裝包方式】 https://blog.csdn.net/weixin_44893902/article/details/121788104 我的版本是v16.13.1 二、安裝nativefier 這是一個GitHub上的開源項目&#xff1a…

C 語言函數

1.0 函數的創建和使用 在C語言中&#xff0c;函數是一種封裝了特定功能的代碼塊&#xff0c;可以被程序中的其他部分調用。函數可以接受輸入參數&#xff0c;并且可以返回一個值。定義一個函數的基本語法如下 #define _CRT_SECURE_NO_WARNINGS #include "stdio.h" …

numpy、ffmpeg都在cpu上面跑

ffmpeg: ffmpeg不支持在GPU上運行。ffmpeg是一個用于處理多媒體數據的工具&#xff0c;它主要在CPU上運行。雖然某些特定的ffmpeg功能&#xff08;如某些視頻編解碼器&#xff09;可以利用GPU進行硬件加速&#xff0c;但這需要特定的硬件和驅動支持&#xff0c;并且并非所有操…

阿里云人工智能平臺PAI部署開源大模型chatglm3之失敗記錄--update:最后成功了!

想學習怎么部署大模型&#xff0c;跟著網上的帖子部署了一個星期&#xff0c;然而沒有成功。失敗的經歷也是經歷&#xff0c;記在這里。 我一共創建了3個實例來部署chatglm3&#xff0c;每個實例都是基于V100創建的&#xff08;當時沒有A10可選了&#xff09;&#xff0c;其顯…

算法工程師第六天(● 454.四數相加II ● 383. 贖金信 ● 15. 三數之和 ● 18. 四數之和 ● 總結 )

參考文獻 代碼隨想錄 一、四數相加 II 給你四個整數數組 nums1、nums2、nums3 和 nums4 &#xff0c;數組長度都是 n &#xff0c;請你計算有多少個元組 (i, j, k, l) 能滿足&#xff1a; 0 < i, j, k, l < nnums1[i] nums2[j] nums3[k] nums4[l] 0 示例 1&#…

x86芯片定制,Ethercat芯片定制,IP服務,適用于運動控制,工業總線等軟硬一體機

x86芯片定制&#xff0c;Ethercat芯片定制 X86平臺 我們的研發工程師已經積累了非常豐富的主板、整機設計經驗&#xff0c;對接您的產品規格場景需求&#xff0c;快速交付樣機&#xff0c;包含主板、BOX整機、平板電腦、CPCI等形態產品。降本、長生命周期、快速交付、及時響應…

C# 如何防止反編譯?C#程序加密混淆保護方法大全

在C#開發中&#xff0c;由于.NET程序集&#xff08;assemblies&#xff09;是基于中間語言&#xff08;Intermediate Language, IL&#xff09;編譯的&#xff0c;這些程序集可以被反編譯回接近原始源代碼的形式。為了保護代碼不被輕易反編譯&#xff0c;開發者可以采取以下幾種…

springsecurity(學習自用)

springsecurity 學習資源&#xff1a; https://blog.csdn.net/qq_45525848/article/details/131142179 springbootspring security 認證&#xff1a; 判斷用戶是否是系統合法用戶過程授權: 判斷系統內用戶可以訪問或具有訪問那些資源權限過程 創建一個springboot項目 如果只…

IEC62056標準體系簡介-2.IEC62056標準體系及對象標識系統(OBIS)

1. IEC 62056標準體系 IEC 62056標準體系目前共包括六部分&#xff0c;見圖1&#xff1a; 第61部分&#xff1a;對象標識系統第62部分&#xff1a;接口類第53部分&#xff1a;COSEM應用層第46部分&#xff1a;使用HDLC&#xff08;High Level Data Link Control&#xff09;協…

Linux多進程和多線程(八)多線程

多線程 線程定義線程與進程線程資源 線程相關命令 pidstat 命令 top 命令ps 命令常見的并發方案 1. 多進程模式2. 多線程模式 創建線程 1. pthread_create() 示例:創建一個線程 2. pthread_exit() 退出線程3. pthread_join() 等待線程結束 示例: 線程分離 創建多個線程 示例 1:…