1. 程式人生 > >2018.2.2

2018.2.2

相同 簡單 clas 一次 ted 有一個 con 沒有 pos

重回algo。

廣度優先算法(BFS)。這個算法會用到隊列的數據結構,簡單說就是先進隊列的結點最後會先出來,後進的後出。隊列裏最開始只有初始結點,讓結點出隊,然後分析每個這個結點能夠連到的結點,如果目標結點沒有被探索過(這裏需要一個標記),標記它為已探索,然後讓他入隊,之後對每個入隊的結點都對相同的處理。直到隊列變為空隊列,就意味著所有能夠搜到的結點都搜完了。

這個算法是O(m+n)的。並且如果在做這個算法的時候多加一個標記,就可以順便用來算其他所有結點相比於初始結點的最小路徑。簡單說就是初始結點的標記為0,那麽從初始結點搜到的結點標記就為1,每搜到的新結點標記相比頭結點加1。

當然還有深度優先算法(DFS)。深度有限算法是一個遞歸算法。它把所有結點分成兩種狀態:已完結和未完結。從初始結點出發搜下一個點,如果沒有點可搜,標記該點為已完結並返回它的頭結點,如果有點可搜,那麽如果是已發現的就無視它,如果未發現,就對該點遞歸該算法。

同樣它也是O(m+n)的。這個算法可以用來給有向圖做拓撲排序。

拓撲排序就是把有向圖的結點做成人體蜈蚣形狀的(餵)。一個顯而易見的思路就是找一個沒有出邊的結點,如果找不到就說明有向圖有內循環,做不了拓撲排序,能找到的話,就刪掉這個結點和與它相連的邊,然後對剩余的有向圖遞歸該算法。

不過實際上也很顯然,在DFS的時候順便加一個標記就可以順手解決拓撲排序問題了。只需要把結點的完結順序記錄下來,然後一字排開就好了。

DFS還有一個應用就是尋找 strongly connected components (SCC),SCC就是一堆結點的集合,在這集合裏面每個結點之間都能互通。一般來說可以把一個巨型圖拆解為不同的SCC的集合。 尋找SCC的kosaraju算法基本流程就是把有向圖的方向倒過來,對這個反向圖做一次DFS,初始點可以隨機的,把結點的完結順序紀錄下來。之後對正向圖再做一次DFS,不過這裏初始點就不能亂選了,要選之前那次DFS中最晚完結的點,以它開始做DFS,當它結束時,此時已完結的結點集合就構成了一個SCC。之後找到新的(此次DFS還沒完結的)最晚完結的點,繼續此次DFS,後面的流程類似,到最後所有點都完結的時候就得到了多個SCC了。

kosaraju算法的證明吧。。。抱歉我又沒看懂。。。這裏面SCC之間臨界結點的部分是比較tricky的,我聽的雲裏霧裏。不過很顯然它也是O(m+n)的。後面光頭哥講了一個SCC的直接應用,就是互聯網網頁之間的有向圖關系,還蠻有趣的。

2018.2.2