數據結構 —— FloydWarshall算法

數據結構 —— FloydWarshall算法

  • FloydWarshall算法
  • 三種最短路徑算法比較
      • 1. Dijkstra算法
      • 2. Bellman-Ford算法
      • 3. Floyd-Warshall算法
      • 總結

我們之前介紹的兩種最短路徑算法都是單源最短路徑,就是我們要指定一個起點來尋找最短路徑,而我們今天介紹的FloydWarshall算法,可以不指定源點,找到最短路徑:

FloydWarshall算法

在介紹FloydWarshall算法之前,我們先來想一個問題,就是:最短路徑要經過多少頂點呢?
在這里插入圖片描述第一種情況他倆之間就是最短距離
在這里插入圖片描述
第二種,中間經過了許多結點
在這里插入圖片描述在這里插入圖片描述
Floyd-Warshall算法是一種在有向圖中尋找所有頂點對之間的最短路徑的算法。它可以在圖中包含負權邊的情況下工作,但是圖中不能包含負權循環。

以下是Floyd-Warshall算法的基本步驟:

  1. 初始化:創建一個n×n的距離矩陣D,其中D[i][j]表示從頂點i到頂點j的最短路徑的長度。如果(i,j)之間沒有直接的邊,則D[i][j]設置為無窮大。對于所有的頂點i,D[i][i]=0。
  1. 對于每一個中間頂點k,更新距離矩陣D。具體來說,對于每一對頂點(i, j),如果D[i][j] > D[i][k] + D[k][j],則更新D[i][j]為D[i][k] + D[k][j]。這相當于檢查是否可以通過k作為中間頂點來獲得從i到j的更短路徑。
  1. 重復步驟2,直到所有可能的中間頂點都被考慮過。
  1. 最后,距離矩陣D中的每個元素D[i][j]將包含從頂點i到頂點j的最短路徑的長度
void FloydWarshall(vector<vector<W>>& vvDest, vector<vector<int>>& vvParentpath)
{// 調整vvDest和vvParentpath的大小與頂點數量一致vvDest.resize(_vertex.size());vvParentpath.resize(_vertex.size());// 初始化距離矩陣為最大權重(表示不可達)// 初始化前驅節點矩陣為-1(表示無前驅節點)for (size_t i = 0; i < _vertex.size(); i++){vvDest[i].resize(_vertex.size(), MAX_W);vvParentpath[i].resize(_vertex.size(), -1);}// 初始化距離矩陣和前驅節點矩陣// 如果兩個頂點間存在直接連接,則設置距離矩陣的相應位置為該連接的權重// 并且設置前驅節點為當前頂點for (size_t i = 0; i < _vertex.size(); i++){for (size_t j = 0; j < _vertex.size(); j++){// 同一頂點到自身的距離為0,前驅節點為-1if (i == j){vvDest[i][j] = 0;vvParentpath[i][j] = -1;}// 如果兩頂點之間有直接連接,并且權重不是最大權重(即可達)if (_matrix[i][j] != MAX_W){vvDest[i][j] = _matrix[i][j];vvParentpath[i][j] = i;}else{// 如果兩頂點之間不可達,前驅節點為-1vvParentpath[i][j] = -1;}}}// 這里是核心部分,遍歷所有頂點作為中間頂點,以檢查是否存在更短路徑for (size_t k = 0; k < _vertex.size(); k++){for (size_t i = 0; i < _vertex.size(); i++){for (size_t j = 0; j < _vertex.size(); j++){// 如果存在通過頂點k作為中間頂點的更短路徑,則更新距離和前驅節點if (vvDest[i][k] != MAX_W && vvDest[k][j] != MAX_W && vvDest[i][k] + vvDest[k][j] < vvDest[i][j]){vvDest[i][j] = vvDest[i][k] + vvDest[k][j];vvParentpath[i][j] = vvParentpath[k][j];}}}// 打印每次迭代后的距離矩陣和前驅節點矩陣(可選)//打印權值和路徑矩陣觀察數據//cout << "     ";//for (size_t i = 0; i < _vertex.size(); i++)//{//	cout << _vertex[i] << " ";//}//cout << endl;for (size_t i = 0; i < _vertex.size(); ++i){cout << _vertex[i] << " ";for (size_t j = 0; j < _vertex.size(); ++j){if (vvDest[i][j] == MAX_W){//cout << "*" << " ";printf("%3c", '*');}else{//cout << vvDest[i][j] << " ";printf("%3d", vvDest[i][j]);}}cout << endl;}cout << endl;for (size_t i = 0; i < _vertex.size(); ++i){for (size_t j = 0; j < _vertex.size(); ++j){//cout << vvParentPath[i][j] << " ";printf("%3d", vvParentpath[i][j]);}cout << endl;}cout << "=================================" << endl;}}
}

我們構建這樣的圖:
在這里插入圖片描述

	void TestFloydWarshall(){const char* str = "12345";Graph<char, int, INT_MAX, true> g(str, strlen(str));g.AddEdge('1', '2', 3);g.AddEdge('1', '3', 8);g.AddEdge('1', '5', -4);g.AddEdge('2', '4', 1);g.AddEdge('2', '5', 7);g.AddEdge('3', '2', 4);g.AddEdge('4', '1', 2);g.AddEdge('4', '3', -5);g.AddEdge('5', '4', 6);vector<vector<int>> vvDist;vector<vector<int>> vvParentPath;g.FloydWarshall(vvDist, vvParentPath);}

在這里插入圖片描述
大家可以對應一下上面的圖,這里注意一下,我們的路徑的數組存儲的是下標,所以每組的第二個圖比上圖中的數值小1,這是正常的。

我們可以把每個結點到其他結點的最短路徑打印出來:

	void TestFloydWarshall(){const char* str = "12345";Graph<char, int, INT_MAX, true> g(str, strlen(str));g.AddEdge('1', '2', 3);g.AddEdge('1', '3', 8);g.AddEdge('1', '5', -4);g.AddEdge('2', '4', 1);g.AddEdge('2', '5', 7);g.AddEdge('3', '2', 4);g.AddEdge('4', '1', 2);g.AddEdge('4', '3', -5);g.AddEdge('5', '4', 6);vector<vector<int>> vvDist;vector<vector<int>> vvParentPath;g.FloydWarshall(vvDist, vvParentPath);// 打印任意兩點之間的最短路徑for (size_t i = 0; i < strlen(str); ++i){g.PrintShortestPath(str[i], vvDist[i], vvParentPath[i]);cout << endl;}}

在這里插入圖片描述
我們也可以把之前小潮的圖拿出來測測:
在這里插入圖片描述

在這里插入圖片描述在這里插入圖片描述

三種最短路徑算法比較

在圖論中,尋找最短路徑是常見的問題,有多種算法可以解決這個問題,包括Dijkstra算法、Bellman-Ford算法和Floyd-Warshall算法。下面是對這三種算法的比較:

1. Dijkstra算法

適用場景:適用于沒有負權邊的加權圖,無論是有向還是無向圖。

優點

  • 時間復雜度較低,使用優先隊列優化后的時間復雜度為O((V+E)logV)。
  • 算法簡單,易于理解和實現。

缺點

  • 不能處理含有負權邊的圖。

2. Bellman-Ford算法

適用場景:適用于任何加權圖,包括含有負權邊的圖,但不能有負權回路。

優點

  • 可以檢測并報告圖中是否存在負權回路。
  • 對于稀疏圖,性能優于Floyd-Warshall算法。

缺點

  • 時間復雜度較高,為O(VE),當E較大時效率低。
  • 每次迭代都需要更新所有邊,即使某些邊的最短路徑已經確定。

3. Floyd-Warshall算法

適用場景:適用于任何加權圖,包括含有負權邊的圖,但不能有負權回路。特別適合于求解所有頂點對之間的最短路徑問題。

優點

  • 可以一次計算出所有頂點對的最短路徑。
  • 算法簡潔,易于理解。

缺點

  • 時間復雜度高,為O(V^3),對于大規模圖的計算效率低下。
  • 需要額外的空間來存儲中間結果,空間復雜度為O(V^2)。

總結

  • 如果只需要求解單源最短路徑問題,且圖中沒有負權邊Dijkstra算法是首選
  • 如果圖中可能含有負權邊,但沒有負權回路,Bellman-Ford算法更為適用
  • 當需要求解所有頂點對之間的最短路徑時,Floyd-Warshall算法是最直接的選擇,盡管它的時間和空間復雜度較高

選擇哪種算法取決于具體的問題背景和圖的特性。

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

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

相關文章

ctfshow-web入門-文件上傳(web166、web167)(web168-web170)免殺繞過

目錄 1、web166 2、web167 3、web168 4、web169 5、web170 1、web166 查看源碼&#xff0c;前端只讓傳 zip 上傳 zip 成功后可以進行下載 隨便搞一個壓縮包&#xff0c;使用記事本編輯&#xff0c;在其內容里插入一句話木馬&#xff1a; 上傳該壓縮包&#xff0c;上傳成功…

附下載 | 100項能源領域網絡與數據安全政策全集(2024版)

能源是工業的糧食&#xff0c;能源安全事關國家根本安全。當今國際局勢風云變幻&#xff0c;全球地緣政治、經濟、科技體系正經歷深刻變化&#xff0c;能源局勢將更加錯綜復雜&#xff0c;威脅能源安全的各種“灰犀牛”“黑天鵝”事件時有發生&#xff0c;促使國際能源版圖深刻…

system V共享內存【Linux】

文章目錄 原理shmgetftokshmat(share memory attach)shmdt&#xff0c;去關聯&#xff08;share memory delete attach&#xff09;shmctl ,刪除共享內存共享內存與管道 原理 共享內存本質讓不同進程看到同一份資源。 申請共享內存&#xff1a; 1、操作系統在物理內存當中申請…

詳解Redis:什么是Redis?

什么是Redis? Redis&#xff08;Remote Dictionary Server&#xff09;是一種開源的、高性能的、基于內存快速讀寫的的數據結構存儲系統&#xff0c;常用于緩存&#xff0c;分布式鎖等場景&#xff1b; Redis常用數據類型有哪些&#xff1f; String(字符串) 適用場景…

Qt中實現讓靜態圖片動起來,創建動畫效果

在現代應用程序開發中&#xff0c;動畫效果是提升用戶體驗的重要元素之一。Qt作為一個強大的跨平臺應用程序框架&#xff0c;提供了豐富的工具和庫來創建各種動畫效果。本文將介紹如何在Qt中使用靜態圖片創建動畫效果。 實現方法一 使用QTimer和QPixmap 1.準備圖片資源&#…

Qt圖形與圖片(Qt位置相關函數、Qt基礎圖形的繪制、雙緩沖機制、顯示SVG格式圖片)

此篇文章介紹幾種主要位置函數及其之間的區別&#xff0c;以及各種與位置相關函數的使用場合&#xff1b;然后&#xff0c;通過一個簡單繪圖工具實例&#xff0c;介紹利用QPainter和QPainterPath兩種方法繪制各種基礎圖形&#xff1b;最后&#xff0c;通過幾個實例介紹如何利用…

暑假自律日記十

7.11 &#xff08;半小時日記打卡之——暑假第十天&#xff09; 日程 8.30起床 9.20到達逸夫樓開始總結區間DP&#xff0c;上午完成了區間DP和四邊形優化部分的學習 下午組隊打了一場去年的牛客多校&#xff0c;壓力有點大&#xff0c;問題也有點多&#xff0c;總而言之&…

GD32F303RET6讀取SGM58031電壓值

1、SGM58031芯片詳解 &#xff08;1&#xff09;SGM58031是一款低功耗&#xff0c;16位精度&#xff0c;delta-sigma (ΔΣ)模數轉換器(ADC)。它從3V到5.5V供電。 &#xff08;2&#xff09;SGM58031包含一個片上參考和振蕩器。它有一個I2C兼容接口&#xff0c;可以選擇四個I2…

深入Memcached鍵值對限制:優化存儲策略

標題&#xff1a;深入Memcached鍵值對限制&#xff1a;優化存儲策略 Memcached作為一種廣泛使用的高性能分布式內存緩存系統&#xff0c;對鍵值對的大小有特定的限制。這些限制不僅關系到緩存效率&#xff0c;還直接影響到緩存數據的組織和內存的使用。本文將深入探討Memcache…

【RHCE】系統服務綜合實驗

一、實驗內容 現有主機 node01 和 node02&#xff0c;完成如下需求&#xff1a; 1、在 node01 主機上提供 DNS 和 WEB 服務 2、dns 服務提供本實驗所有主機名解析 3、web服務提供 www.rhce.com 虛擬主機 4、該虛擬主機的documentroot目錄在 /nfs/rhce 目錄 5、該目錄由 node02…

Python | Leetcode Python題解之第229題多數元素II

題目&#xff1a; 題解&#xff1a; class Solution:def majorityElement(self, nums: List[int]) -> List[int]:cnt {}ans []for v in nums:if v in cnt:cnt[v] 1else:cnt[v] 1for item in cnt.keys():if cnt[item] > len(nums)//3:ans.append(item)return ans

【conda】解決 An HTTP error occurred when trying to retrieve this URL.問題

1. 修改SSL驗證 如果其他方法無效&#xff0c;還可以嘗試關閉SSL驗證來解決問題。具體操作如下&#xff1a; 在終端中輸入以下命令&#xff0c;關閉SSL驗證&#xff1a; conda config --set ssl_verify false或者&#xff0c;在conda的配置文件&#xff08;.condarc&#xff0…

為什么渲染農場渲染的是幀,而不是視頻?

在3D動畫產業的壯闊畫卷中&#xff0c;渲染農場作為幕后英雄&#xff0c;以其龐大的計算能力支撐起無數視覺奇觀的誕生。這些由高性能計算機集群構成的系統&#xff0c;通過獨特的逐幀渲染策略&#xff0c;解鎖了單機難以企及的創作自由與效率。本文將深入剖析這一策略背后的邏…

maven7——(重要,構建項目)maven項目構建(命令)

Maven的常用命令管理項目的生命周期 clean命令 清除編譯產生的target文件夾內容&#xff0c;可以配合相應命令在cmd中使用&#xff0c;如mvn clean package&#xff0c; mvn clean test D:\工作\公司培訓-4班\day20\day20\untitled1>mvn clean compile命令 該命令可以…

element如何實現自定義表頭?

有時候我們需要實現自定義表頭,例如表頭里加按鈕啥的,這時候就需要用到自定義表頭,但是官方對自定義表頭的使用寫的還是比較簡單,今天就來詳細說說 在需要使用自定義表頭的表頭上使用:render-header來啟用自定義表頭: <el-table-column :render-header="button&…

機器學習開源分子生成系列(2)-基于三維形狀和靜電相似性的DeepFMPO v3D安裝及使用

前言 本文是基于 3D 的分子生成方法DeepFMPO v3D的介紹及安裝使用。 一、DeepFMPO v3D是什么&#xff1f; github代碼介紹文章 在藥物發現中&#xff0c;如何尋找具新穎性和結構多樣性的候選分子是頗受藥物設計科學家關注的問題。通過虛擬篩選的化學空間搜索往往會受限于篩選…

Linux賬戶和組管理——用戶密碼文件,工作組賬號文件,用戶管理

#### 用戶密碼文件 - /etc/shadow存儲密碼加密后的密文&#xff0c;又稱為“影子文件”&#xff0c;該文件為了保證了賬戶密碼的安全性只有 root 賬戶擁有讀權限&#xff0c;注意&#xff1a;若該文件權限發生變化&#xff0c;需要留心惡意攻擊 bash [rootserver ~]# ll /etc/…

linux之棧溢出分析

我們來創建一個例子&#xff0c;其中包含一個段錯誤&#xff0c;這次是由于棧溢出導致的。這是一個常見的錯誤&#xff0c;通常發生在程序遞歸調用深度過大&#xff0c;超出了為棧分配的內存空間。 下面是一個簡單的C程序&#xff0c;stack_overflow_example.c&#xff0c;它通…

優化與改進之輕量級Transformer - Transformer教程

在自然語言處理&#xff08;NLP&#xff09;的世界里&#xff0c;Transformer模型無疑是一顆璀璨的明珠。自從它在2017年被提出以來&#xff0c;就憑借其強大的性能和優雅的設計贏得了廣泛的關注和應用。然而&#xff0c;隨著應用的深入&#xff0c;Transformer的體量和計算資源…

牛頓力學和拉格朗日力學求解atwood machine問題對比

一個半徑為 R R R、轉動慣量為 I I I 的圓盤。繩子與圓盤無滑動&#xff0c;質量 m 2 m_2 m2? 的物體在重力 g g g 作用下下墜&#xff0c;帶動質量 m 1 m_1 m1? 的物體上升。求 m 1 m_1 m1?和 m 2 m_2 m2? 的加速度 a a a。 牛頓力學方法 對質量 m 1 m_1 m1? 和 …