終於來到spfa演算法了!之前已經說明過了bellman_ford演算法 ,我們今天說明的spfa演算法僅僅只是對該演算法的乙個優化。
bellman_ford演算法會遍歷所有的邊,但是有很多的邊遍歷了其實沒有什麼意義,我們只用遍歷那些到源點距離變小的點所連線的邊即可,只有當乙個點的前驅結點更新了,該節點才會得到更新;因此考慮到這一點,我們將建立乙個佇列每一次加入距離被更新的結點。
值得注意的是
st陣列的作用:判斷當前的點是否已經加入到佇列當中了;已經加入佇列的結點就不需要反覆的把該點加入到佇列中了,就算此次還是會更新到源點的距離,那只用更新一下數值而不用加入到佇列當中。
即便不使用st陣列最終也沒有什麼關係,但是使用的好處在於可以提公升效率。
spfa演算法看上去和dijstra演算法長得有一些像但是其中的意義還是相差甚遠的:
1] dijkstra演算法中的st陣列儲存的是當前確定了到源點距離最小的點,且一旦確定了最小那麼就不可逆了(不可標記為true後改變為false);spfa演算法中的st陣列僅僅只是表示的當前發生過更新的點,且spfa中的st陣列可逆(可以在標記為true之後又標記為false)。順帶一提的是bfs中的st陣列記錄的是當前已經被遍歷過的點。
2] dijkstra演算法裡使用的是優先佇列儲存的是當前未確定最小距離的點,目的是快速的取出當前到源點距離最小的點;spfa演算法中使用的是佇列(你也可以使用別的資料結構),目的只是記錄一下當前發生過更新的點。
⭐️bellman_ford演算法裡最後return-1的判斷條件寫的是dist[n]>0x3f3f3f3f/2;而spfa演算法寫的是dist[n]==0x3f3f3f3f;其原因在於bellman_ford演算法會遍歷所有的邊,因此不管是不是和源點連通的邊它都會得到更新;但是spfa演算法不一樣,它相當於採用了bfs,因此遍歷到的結點都是與源點連通的,因此如果你要求的n和源點不連通,它不會得到更新,還是保持的0x3f3f3f3f。
⭐️ bellman_ford演算法可以存在負權迴路,是因為其迴圈的次數是有限制的因此最終不會發生死迴圈;但是spfa演算法不可以,由於用了佇列來儲存,只要發生了更新就會不斷的入隊,因此假如有負權迴路請你不要用spfa否則會死迴圈。
⭐️由於spfa演算法是由bellman_ford演算法優化而來,在最壞的情況下時間複雜度和它一樣即時間複雜度為 o(nm)o(nm) ,假如題目時間允許可以直接用spfa演算法去解dijkstra演算法的題目。(好像spfa有點小小萬能的感覺?)
⭐️求負環一般使用spfa演算法,方法是用乙個cnt陣列記錄每個點到源點的邊數,乙個點被更新一次就+1,一旦有點的邊數達到了n那就證明存在了負環。
推薦演算法注意事項總結
本文總結了多種推薦場景中的注意事項,或者推薦中比較關鍵的因素,不涉及演算法描述,僅僅說明關注點,僅供參考。推薦演算法有很多種,從演算法的角度來說,我認為主要由以下幾種 協同過濾系列 基於item和user 機器學習分類系列 喜歡和不喜歡二分類,或者回歸中的分值代表喜歡程度 矩陣分解系列 mahout...
演算法 程式設計的注意事項
一 定義變數,得明確每個變數的意義,在實現程式邏輯時,得維護好變數 二 實現函式,實現某個程式邏輯時,應該想到這個程式的前提條件,例如 檢查大小是否越界 遞迴是否有終點 遞迴是否有返回 三 處理好邊界問題,適當用注釋寫出來,會方便很多 四 迴圈不變數 在迴圈的時候 改變變數的值,但是不改變變數的含義...
java DOM 注意事項
1.w3c把標籤內的文字部分也定義成乙個node 2.element物件代表的是xml文件中的標籤元素 繼承於node,亦是node的最主要的子物件 3.attr實際上是包含在element中的,它並不能被看作是element的子物件,因而在dom中attr並不是dom樹的一部分,所以node中的 ...