今天晚上無心翻到一個圖的文章,查了一下感受網上實現和其餘都好複雜,因此本身按理解搞了一下,不知道是我實現是否是錯了...感受還好~進入正題,先仍是來點理論知識,不過大可能是本身的想法,不必定都對,能夠糾正。內容來源來自《JavaScript 數據結構和算法》。javascript
圖是一種數學模型,和數學掛勾通常都會比較複雜,因此形象的理解成最簡單的模型,點-線 模型。其實最簡單的是 1 個點的模型,涉及 2 個點還好,3 個點事後模型就會做出相應的改變。java
這裏用簡單的語言來講圖中的二元關係,不過仍是先假設一點數學符號:node
G => 表示全部的頂點集合算法
V => 表示頂點數據庫
E => 表示邊,抽象意義上是無向邊數據結構
那麼用數學來表示就是:G=<V, E>數據結構和算法
其實根本不用理解數學的模型,我這裏理解是隻須要知道這是一個點-線模型就能夠了。函數
這裏有兩種表示方法:表和矩陣,其間都是鄰接關係工具
這裏我有一個測試圖,在網上弄的,雖然是無向圖,其實在咱們代碼中,確定是有向的,是入口的問題:測試
圖的結構肯定事後,就能夠作出表的結構了,這裏我沒有用方向,由於我理解的圖是一個不能簡單表示的,理解成座標系更好理解一點。分爲:x, y 軸的方式。其中,x0 表示開始,後面表示相鄰的點,按順時針排列(不必定按這個順序)。
在代碼中表示,沒有圖形那麼直觀,因此須要映射成代碼模型,這裏簡單實現一下,可是不具有不少功能。
假設:
class G => 一個圖的類,包括圖的定義和經常使用遍歷方法
this.V => 表示點集合的個數,可是這裏我捨棄了 0 的位置
this.T => 我按數據庫表的方式理解命名的,關係的集合
this.E => 邊的個數
this.visited => 訪問過的 bool 集合,其實就是標記
this.defined => 工具小函數,是否認義過,與圖無關
因此最後有關的符號有:
G、V、T、E
是否是感受一會兒變簡單了,不過程序的抽象有一個上層,那就是類。
而後我這裏按計算機的方式,定義了輸入、輸出函數:input、output
class G { constructor(V) { this.V = V; this.T = []; this.E = 0; this.visited = []; for (let v = 0; v < this.V; ++v) { this.T[v] = []; this.T[v].push(-1); } this.defined = s => s !== void 0; } input(v, w) { this.T[v].push(w); this.T[w].push(v); this.E++; return this; } output() { console.table(this.T); } }
而後可以看出,其實邊是由點的鏈接組成的,恰好符合數學的定義,而且與相鄰有相關性。
那麼,實現告終構,還應該有其餘做用,那麼接下來看一下遍歷算法:深度遍歷(DFS) 和 廣度遍歷(BFS)。準確來講應該是優先採用什麼策略的遍歷方式。其實我這裏的實現感受...很差,和樹關係大了點,不過樹的大集合就可以上升到圖。
dfs(v) { this.visited[v] = true; if (this.defined( this.T[v] )) { console.log('老孫到此一遊:' + v); } this.T[v].forEach(t => { if (t !== -1 && !this.visited[t]) { this.dfs(t); } }); }
對於深度遍歷,是將圖按一個固定方向,縱向的結果,因此是一個遞歸的結構。
bfs(node) { this.visited[node] = true; var queue = []; queue.push(node); while(queue.length > 0) { var v = queue.shift(); if(this.defined( this.T[v] )) { console.log('老孫到此一遊:' + v); } this.T[v].forEach(t => { if(t !== -1 && !this.visited[t]) { this.visited[t] = true; queue.push(t); } }); } }
對於廣度遍歷,是將圖按一個固定方向,橫向的結果,因此是一個鏈式進出的關係,這裏是用隊列,在 JS 中作隊列這種先進先出比較簡單。
// 測試代碼 var v = [1, 2, 3, 4, 5]; let g = new G( v.length + 1 ); g.input(1, 2).input(1, 5) .input(2, 4).input(2, 5).input(2, 3) .input(3, 4) .input(4, 5) .output(); g.dfs(1); console.log('------------'); // 讓它失憶一下 g.visited = []; g.bfs(1);
……-_-# 簡單玩一下,睡覺了 zZZ