說明:
本文僅提供關於兩個算法的正確性的證明,不涉及對算法的過程描述和實現細節
本人算法菜鳥一枚,提供的證明僅是自己的思路,不保證正確,僅供參考,若有錯誤,歡迎拍磚指正
-------------------------------------------
Dijkstra算法和Floyd算法用於求解連通圖中任意兩個頂點之間的最短路徑
Dijksra算法從一個頂點v0出發,每次為一個頂點vi確定到達v0的最小路徑
Dijkstra算法用distance[i]記錄頂點vi到v0的最短路徑,用path[i]記錄在最短路徑中vi頂點的前繼頂點,另外再用found[i]來標志頂點vi的最短路徑是否已經確定
Dijkstra算法做出了這樣一個判斷:每次從尚未確定最小路徑的頂點中(一下簡稱 未定頂點)挑選一個distance值最小的頂點vj,則該頂點對應的distance[j]必定是vj的真實的最小路徑長度,下面證明這個判斷:
對於任意一個未定頂點,其最小路徑中必定至少包含一個已定頂點(至少會包含v0),則該路徑中至少有一個未定頂點vm以一個已定頂點vn為前繼頂點,而length(v0-vn-vm) >= diatance[m] >= distance[j],也就說任意一個未定頂點的最小路徑長必定不小於distance[j],由此就可以確定distance[j]必定是vj真實的最小路徑長
Dijkstra算法的復雜度是n^2,每次確定一個頂點的最短路徑,而確定一個頂點的最短路徑需要遍歷並比較distance數組,並且確定之后需要遍歷更新distance數組,所以是n*n的開銷
--------------------------------
Floyd算法的執行邏輯甚為簡單,包含了三個循環的嵌套;其思路是遍歷圖中的每一個點,針對這個點vm,遍歷圖中任意兩個頂點的兩兩組合vi和vj,比較vi和vj當前的最短連接和通過vm的連接的大小,並且把新的當前最短連接重置為其中更小的那個值;這樣一圈遍歷下來,就可以保證得到圖中任意兩個頂點之間的最小距離
這看起來並不靠譜,因為在最初vi和vm、vj和vm之間的最小路徑都尚未安全確定下來的時候,如何能夠馬上就拿來比較,這時的比較不應該是無效的嗎?
但是事實上並不需要每一步都實現嚴格的有效的比較,因為全部遍歷下來之后,肯定會發生一次有效的比較
下面給出證明:
假設vi、vj之間的最小路徑一共包括x個其它頂點,顯然這條路徑也確定了其中任何兩個頂點之間的最小路徑,否則比如vm、vn之間有不屬於當前路徑的最小子路徑,則用該子路徑替代當前的子路徑,就可以得到更小的vi、vj之間的最小路徑
對於這條路徑上的任意三個相鄰(至少會有一組相鄰三頂點)頂點vm1、vm2、vm3,當遍歷到vm2時,顯然此時vm1-vm2-vm3這條最小子路徑就會被連接起來(因為這條路徑必定是vm1到vm3的最小子路徑);事實上,當遍歷到這條最小路徑上的任意一個頂點的時候(除了vi、vj),就會把相鄰的兩個頂點連接起來;當所有頂點都被遍歷之后,這x個頂點也必定已經把其在最小路徑上相鄰的頂點全都連接完畢,包括分別在兩端的vi和vj頂點;換句話說,vi和vj之間的最小子路徑必定已經被找到
Floyd算法的復雜度為n^3