關(guān)于弗洛伊德算法求最短路徑詳解
弗洛伊德算法介紹
- 和迪杰斯特拉算法一 樣, 弗洛伊德(Floyd)算法也是一種用于尋找給定的加權(quán)圖中頂點(diǎn)間最短路徑的算法。
- 弗洛伊德算法(Floyd)計(jì)算圖中各個(gè)頂點(diǎn)之間的最短路徑
- 迪杰斯特拉算法用于計(jì)算圖中某-一個(gè)頂點(diǎn)到其他項(xiàng)點(diǎn)的最短路徑。
- 弗洛伊德算法VS迪杰斯特拉算法:迪杰斯特拉算法通過(guò)選定的被訪問(wèn)頂點(diǎn),求出從出發(fā)訪問(wèn)頂點(diǎn)到其他項(xiàng)點(diǎn)的最短路徑:弗洛伊德算法中每-個(gè)頂點(diǎn)都是出發(fā)訪問(wèn)點(diǎn),所以需要將每-一個(gè)頂點(diǎn)看做被訪問(wèn)頂點(diǎn),求出從每一個(gè)頂點(diǎn)到其他頂點(diǎn)的最短路徑。
- 算法的時(shí)間復(fù)雜度為O(N3),空間復(fù)雜度為O(N2)。
- 優(yōu)點(diǎn):容易理解,可以算出任意兩個(gè)節(jié)點(diǎn)之間的最短距離,代碼編寫(xiě)簡(jiǎn)單。
- 缺點(diǎn):時(shí)間復(fù)雜度比較高,不適合計(jì)算大量數(shù)據(jù)。
弗洛伊德算法思想
通過(guò)一個(gè)圖的權(quán)值矩陣求出它的每?jī)牲c(diǎn)間的最短路徑矩陣。
從圖的帶權(quán)鄰接矩陣A=[a(i,j)] n×n開(kāi)始,遞歸地進(jìn)行n次更新,即由矩陣D(0)=A,按一個(gè)公式,構(gòu)造出矩陣D(1);又用同樣地公式由D(1)構(gòu)造出D(2);……;
最后又用同樣的公式由D(n-1)構(gòu)造出矩陣D(n)。矩陣D(n)的i行j列元素便是i號(hào)頂點(diǎn)到j(luò)號(hào)頂點(diǎn)的最短路徑長(zhǎng)度,稱D(n)為圖的距離矩陣
同時(shí)還可引入一個(gè)后繼節(jié)點(diǎn)矩陣path來(lái)記錄兩點(diǎn)間的最短路徑。
采用的是(松弛技術(shù)),對(duì)在i和j之間的所有其他點(diǎn)進(jìn)行一次松弛。所以時(shí)間復(fù)雜度為O(n^3);
其狀態(tài)轉(zhuǎn)移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]}
map[i,j]表示i到j(luò)的最短距離,K是窮舉i,j的斷點(diǎn),map[n,n]初值應(yīng)該為0.當(dāng)然,如果這條路沒(méi)有通的話,還必須特殊處理,比如沒(méi)有map[i,k]這條路
算法原理
Floyd算法的原理是動(dòng)態(tài)規(guī)劃。
設(shè)Di,j,k為從i到j(luò)的只以(1…k)集合中的節(jié)點(diǎn)為中間節(jié)點(diǎn)的最短路徑的長(zhǎng)度。
代碼實(shí)現(xiàn):
public class Test1 { public static void main(String[] args) { System.out.println("請(qǐng)輸入有幾個(gè)頂點(diǎn):"); Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); char[] vertex = new char[n]; System.out.println("請(qǐng)輸入各個(gè)頂點(diǎn)的符號(hào),每個(gè)字符用空格分隔:"); for (int i = 0; i < n; i++) { vertex[i] = scanner.next().charAt(0); } int[][] arr = new int[n][n]; System.out.println("請(qǐng)輸入各個(gè)頂點(diǎn)在二維表之間的距離,不能直達(dá)的用100表示:"); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { arr[i][j] = scanner.nextInt(); } } Graph gp = new Graph(vertex, arr, n); gp.floyd(); gp.show(vertex); } } //創(chuàng)建圖 class Graph { private char[] vertex; private int[][] dis; // 從頂點(diǎn)出發(fā)到其他節(jié)點(diǎn)的距離 private int[][] pre; // 目標(biāo)節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn) // 頂點(diǎn)數(shù)組 鄰接矩陣 長(zhǎng)度大小 public Graph(char[] vertex, int[][] dis, int len) { this.vertex = vertex; this.dis = dis; this.pre = new int[len][len]; // 對(duì)pre數(shù)組進(jìn)行初始化 for (int i = 0; i < len; i++) { Arrays.fill(pre[i], i); } } public void show(char[] vertex) { for (int i = 0; i < dis.length; i++) { for (int j = 0; j < dis.length; j++) { System.out.print(vertex[pre[i][j]] + " "); } System.out.println(); for (int j = 0; j < dis.length; j++) { System.out.print("( " + vertex[i] + " -> " + vertex[j] + " 的最短路徑 " + dis[i][j] + " ) "); } System.out.println(); } } // 弗洛伊德算法 public void floyd() { int len = 0; // 從中間節(jié)點(diǎn)進(jìn)行遍歷 for (int k = 0; k < dis.length; k++) { // 對(duì)出發(fā)節(jié)點(diǎn)進(jìn)行遍歷 for (int i = 0; i < dis.length; i++) { // 遍歷終點(diǎn)節(jié)點(diǎn) for (int j = 0; j < dis.length; j++) { len = dis[i][k] + dis[k][j]; if (len < dis[i][j]) { dis[i][j] = len; pre[i][j] = pre[k][j]; } } } } } }
結(jié)果展示:
示例1:
結(jié)果:
示例2:
結(jié)果:
到此這篇關(guān)于關(guān)于弗洛伊德算法求最短路徑詳解的文章就介紹到這了,更多相關(guān)弗洛伊德算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解SpringBoot構(gòu)建的Web項(xiàng)目如何在服務(wù)端校驗(yàn)表單輸入
這篇文章主要介紹了詳解SpringBoot構(gòu)建的Web項(xiàng)目如何在服務(wù)端校驗(yàn)表單輸入,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10基于java實(shí)現(xiàn)斗地主代碼實(shí)例解析
這篇文章主要介紹了基于java實(shí)現(xiàn)斗地主代碼實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07SpringBoot3.0+SpringSecurity6.0+JWT的實(shí)現(xiàn)
本文主要介紹了SpringBoot3.0+SpringSecurity6.0+JWT的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11SpringDataJpa多表操作的實(shí)現(xiàn)
開(kāi)發(fā)過(guò)程中會(huì)有很多多表的操作,他們之間有著各種關(guān)系,本文主要介紹了SpringDataJpa多表操作的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11SpringBoot使用hutool-captcha實(shí)現(xiàn)驗(yàn)證碼生成與驗(yàn)證
在springboot的登陸頁(yè)面中為了防止機(jī)器大規(guī)模注冊(cè),機(jī)器暴力破解數(shù)據(jù)密碼等危害,需要驗(yàn)證隨機(jī)生成的驗(yàn)證碼,本文主要介紹了SpringBoot使用hutool-captcha實(shí)現(xiàn)驗(yàn)證碼生成與驗(yàn)證,感興趣的可以了解一下2023-12-12Spring Boot學(xué)習(xí)入門(mén)之統(tǒng)一異常處理詳解
我們?cè)谧鯳eb應(yīng)用的時(shí)候,請(qǐng)求處理過(guò)程中發(fā)生錯(cuò)誤是非常常見(jiàn)的情況。下面這篇文章主要給大家介紹了關(guān)于Spring Boot學(xué)習(xí)入門(mén)之統(tǒng)一異常處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-09-09SpringBoot+ThreadLocal+AbstractRoutingDataSource實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源
最近在做業(yè)務(wù)需求時(shí),需要從不同的數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)然后寫(xiě)入到當(dāng)前數(shù)據(jù)庫(kù)中,因此涉及到切換數(shù)據(jù)源問(wèn)題,所以本文采用ThreadLocal+AbstractRoutingDataSource來(lái)模擬實(shí)現(xiàn)dynamic-datasource-spring-boot-starter中線程數(shù)據(jù)源切換,需要的朋友可以參考下2023-08-08Springboot關(guān)于自定義stater的yml無(wú)法提示問(wèn)題解決方案
這篇文章主要介紹了Springboot關(guān)于自定義stater的yml無(wú)法提示問(wèn)題及解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06Java continue break制作簡(jiǎn)單聊天室程序
這篇文章主要為大家詳細(xì)介紹了Java continue break制作簡(jiǎn)單聊天室程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10