圖形算法可視化

最近看了一些和圖形、算法可視化相關的文章和代碼,挺有意思,因而本身也學着作了些東西。html

迷宮生成算法

迷宮小時候玩過,但歷來沒琢磨過迷宮是怎麼設計的,覺得就是有人慢慢畫出來的。看過網上這篇文章後,才知道,原來還能夠隨機生成:git

Maze Generation - Visualizing Algorithmsgithub

本身找了些資料參考,試着實現了幾種以後,才慢慢領會到其中的一些原理。算法

算法中討論的迷宮知足一個條件:迷宮中任意兩點間有且只有一條路徑數組

要隨機生成知足這樣條件的迷宮,看起來很複雜啊。可是換個思路以後,就發現問題沒那麼複雜了。app

「樹」其實就知足這個條件:佈局

  • 全部的枝葉均可以經過樹枝、樹幹連通
  • 因爲枝幹不交叉,沒有環,因此枝葉間連通的路徑是惟一的

因此,生成隨機的迷宮的問題,就轉化爲生成隨機的樹的過程。進一步,能夠拆分爲如下過程:動畫

  • 在迷宮網格內隨機選擇一個點做爲「樹根」
  • 從樹根開始,向隨機選擇的某一方向開始生長
  • 直到樹的枝幹經過不斷生長、分叉充滿迷宮的全部網格

迷宮生成的不一樣算法,區別主要在兩點:spa

  • 從一個位置開始生成後一直向隨機方向延伸的最大長度:有的是延伸一個網格後當即更換生長點,有的則是直到沒法繼續延伸後才更換生長點
  • 更換生長點時選擇位置的方式:有的是記錄當前枝幹通過的網格,依次後退,有的乾脆是徹底隨機選擇一個有可能向外生長的點

深度優先算法

深度優先算法,也叫遞歸回溯算法。它會一直向隨機方向生長,直到沒法生成的位置,向後回退一格,繼續生長,直到全部網格被填充。設計

深度優先算法生成的迷宮

深度優先算法生成的迷宮,會有比較明顯的長路徑,這是由於樹在一開始生成的時候,空間比較充裕,會有一些長的枝條產生。

Prim 算法

Prim 算法不會一直沿着一條路徑進行探索,而是不斷嘗試隨機的生長點。因此 Prim 算法生成的迷宮,分叉會比較多:

Prim 算法生成的迷宮

算法實現

綜合以上兩種算法,我既不但願有過長的路徑,也不但願有太多的分叉,因此我採用的思路的嘗試沿着一條路徑延伸最多必定的長度,而後再隨機選擇生長點執行相同的過程。

下圖是在 40*40 的迷宮網格,每條枝幹最多生長15個網格的效果:

迷宮生成算法 - 開始

這是執行了一段時間以後,迷宮大部分區域已經走過:

迷宮生成算法 - 執行中

這是最後的效果:

迷宮生成算法 - 完成

項目地址:luobotang/maze
在線DEMO:迷宮生成算法 - luobotang

算法可視化

上面例子中的迷宮生成算法過程,迷宮網格是經過 HTML 的 <table> 實現,相鄰網格的連通效果,則是藉助 CSS 的邊框樣式。

整個迷宮的全部網格由二維數組表示,每一個網格的狀態包含是否被訪問、與相鄰網格的連通狀況等。

算法的執行過程由定時器驅動,每次執行一步,從而有動畫的效果。

最短路徑算法

與圖相關的最短路徑算法,在生活中應該是有着普遍的應用了吧,從一個位置到另外一個位置,藉助已有的路網,計算最短的路徑。固然,還會由於路況、臨時障礙,以及用戶的我的偏好而產生不一樣結果。

對於「圖」上,基本要素就是:

  • 節點
  • 邊:根據場景的不一樣,還會有方向、權重屬性

Dijkstra 算法

Dijkstra 算法是用於計算最短路徑的比較著名的一種算法,早在1956年就發表了。

Dijkstra 算法若是看算法的詳細執行過程,有點複雜,可是其基本思路在作過以後會發現,貌似很簡單。

已肯定 A 到 B 的最短路徑,B 與 C 相連,且 A 到 B 的距離加上 B 到 C 的距離,小於當前 A 到 C 的距離,那麼 A 到 B 再到 C 就是 A 到 C 的最短路徑。

圖示例

如上圖所示,最初從 A 來看,到 C 的最短路徑是 A -> C,距離是 4。但繼續探索到 B 後,發現 A -> B 加上 B -> C 距離只有 3,比 A -> C 的距離要小,因此 A 到 C 的最短路徑更新爲:A -> B -> C。

算法實現

基本思路上面都介紹了,細節就是每次探索節點時,都選擇當前未探索過的到源點距離最短的節點,這樣能夠源點到當前點的路徑已是最短路徑。

算法可視化

圖的可視化比較複雜了,只是繪製出來其實不難,但要將節點、邊進行合理佈局就比較麻煩,是另外一個話題了。

我選擇用 vis.js 提供的 Network 來繪製圖形,而後經過逐步執行算法來更新圖形。

這是初始狀態:

Dijkstra 算法 - 開始

執行過程當中,會記錄節點是否被訪問,以及當前的最短路徑和對應的距離:

Dijkstra 算法 - 執行中

所有執行完成後,就獲得了源點開始到圖中全部節點的最短路徑:

Dijkstra 算法 - 完成

項目地址:luobotang/graph
DEMO:Dijkstra 算法 - luobotang

項目的 Github Pages 配置有點問題,只能下載到本地以後再打開頁面了。

結語

其實上面這些實現起來並無特別困難,有不少現成的資料和代碼能夠利用。可是無論什麼飯,都得本身吃過、消化過纔是本身的。因此,我把本身吸取的「養分」記錄下來,若是你也有興趣,不妨本身上手一試。

最後,感謝閱讀!

相關文章
相關標籤/搜索