摘要:圖關聯矩陣在關聯矩陣表示的圖中,矩陣的行表示頂點,列表示邊。如圖,頂點數是,邊的數量是,用鄰接矩陣表示圖需要的空間是,而使用關聯矩陣表示圖需要的空間是。廣度優先搜索算法數據結構是隊列。深度優先搜索算法數據結構是棧。
定義
圖和散列表、二叉樹一樣,是一種非線性數據結構。如圖1所示,圖由一系列頂點以及連接頂點的邊構成。由一條邊連接在一起的頂點成為相鄰頂點,比如A和B、A和D是相鄰的,而A和E不是相鄰的。一個頂點相鄰頂點的數量叫作度,比如A的度為3、D的度為4。路徑指相鄰頂點的一個連續序列,如ABEI、ACDG;簡單路徑指不包含重復頂點的路徑(除環外),如ADG;環指首尾頂點相同的路徑,如ADCA,環也屬于簡單路徑。如果圖中每兩個頂點之間都有路徑相連,則稱該圖是連通的。
如圖2,如果圖中的邊具有方向,稱該圖為有向圖。如果圖中的邊是雙向的,則該圖是強連通的,例如圖3中的C和D是強連通的。圖也可以是加權的,例如圖3中的每條邊都有權值。
圖可以用來解決計算機中的很多問題,比如搜索圖中的一個特定頂點或搜索一條特定邊,尋找圖中的一條路徑(從一個頂點到另一個頂點) ,尋找兩個頂點之間的最短路徑,以及環檢測。
圖的表示圖的表示方式有多種,沒有絕對正確的表示方式,采用哪種方式取決于圖的類型和待解決的問題。這里介紹三種方式:鄰接矩陣、鄰接表、關聯矩陣。
鄰接矩陣鄰接矩陣用一個二維數組來表示圖中頂點的連接情況;如果索引為i的節點和索引為j的節點連接,則array[i][j] === 1,否則array[i][j] === 0,如圖4。鄰接矩陣的缺點是,如果圖不是強連通的,矩陣中就會出現很多0,從而計算機需要浪費存儲空間來表示根本不存在的邊。例如,即使某一頂點只有一個相鄰頂點,也需要一整行來表示該頂點的連接情況,
鄰接表由圖中每個頂點的相鄰頂點的列表所組成,如圖5。只要能表示一對多的數據結構,都可以用來描述鄰接表,比如多維列表(數組)、鏈表、散列表、字典等。
在大多數情況下,鄰接表是更好的選擇,但鄰接矩陣也有其優點,比如要判斷頂點A和B是否相鄰,鄰接矩陣比鄰接表要快。
圖5
關聯矩陣在關聯矩陣表示的圖中,矩陣的行表示頂點,列表示邊。如圖6所示,我們使用二維數組來表示兩者之間的連通性,如果頂點A是邊E的入射點,則array[A][E] === 1;否則,array[A][E] === 0。
關聯矩陣通常用于邊的數量比頂點少的情況下,以節省空間和內存。如圖6,頂點數是5,邊的數量是6,用鄰接矩陣表示圖需要的空間是5*5=25,而使用關聯矩陣表示圖需要的空間是5*6=30。
圖6
創建圖類首先首先聲明類的骨架:
function Graph() { var vertices = []; var adjList = new Dictionary(); }
其中Dictionary類的實現參考之前的文章字典。
我們使用數組 vertices 來存儲圖中所有頂點的名字,以及字典 adjList 來存儲鄰接表。字典將會使用頂點的名字作為鍵,鄰接頂點列表作為值。
接下來實現向圖中添加頂點的方法:
this.addVertex = function(v){ vertices.push(v); adjList.set(v, []); };
該方法接受頂點 v 作為參數。我們將該頂點添加到頂點列表 vertices 中,并且在鄰接表中,設置頂點 v 作為鍵對應的字典值為一個空數組。
接著實現一個點到另一個點的連接:
this.addEdge = function(v, w){ adjList.get(v).push(w); adjList.get(w).push(v); };
這個方法接受兩個頂點作為參數。首先,我們通過將 w 加入到 v 的鄰接表中,添加了一條自頂
點 v 到頂點 w 的邊。如果是有向圖,則只需要該方法的第一行代碼就行了。我們這里要實現無向圖,我們需要添加一條自 w 向 v 的邊,即該方法的第二行代碼。
使用該圖類進行簡單的測試:
var graph = new Graph(); var myVertices = ["A","B","C","D"]; for (var i=0; i上述代碼生成圖對應的鄰接表為:
圖的遍歷
A -> B C
B -> A D
C -> A D
D -> B C有兩種算法可以對圖進行遍歷:廣度優先搜索(Breadth-First Search,BFS)和深度優先搜索(Depth-First Search,DFS)。圖遍歷可以用來尋找特定的頂點或尋找兩個頂點之間的路徑,檢查圖是否連通,檢查圖是否含有環等。
圖遍歷算法的思路是追蹤每個第一次訪問的節點,并且追蹤有哪些節點還沒有被完全探索。對于兩種圖遍歷算法,都需要明確指出第一個被訪問的頂點。
完全探索一個頂點需要查看該頂點的每一條邊。對于每一條邊所連接的沒有被訪問過的頂點,將其標注為被發現的,并將其加進待訪問頂點列表中。
我們用三種狀態來反映頂點的狀態:白色:表示該頂點還沒有被訪問。
灰色:表示該頂點被訪問過,但并未被探索過。
黑色:表示該頂點被訪問過且被完全探索過。
因為只有這三種狀態,初始狀態是白色,因此每個頂點至多訪問兩次,這樣做能夠保證算法的效率。
廣度優先搜索算法和深度優先搜索算法基本上是相同的,只是待訪問頂點列表的數據結構不同。
廣度優先搜索算法:數據結構是隊列。通過將頂點存入隊列中,最先入隊列的頂點先被探索。
深度優先搜索算法:數據結構是棧。通過將頂點存入棧中,沿著路徑探索頂點,存在新的相鄰頂點就去訪問。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91883.html
摘要:強烈推薦上值得前端學習的數據結構與算法項目,包含圖的演示過程與視頻講解。該倉庫包含了多種基于的算法與數據結構,提供進一步閱讀的解釋和鏈接。數據結構和算法必知必會的個代碼實現。 showImg(https://segmentfault.com/img/bVbvpYZ); 前言 算法為王。想學好前端,先練好內功,內功不行,就算招式練的再花哨,終究成不了高手;只有內功深厚者,前端之路才會走得...
摘要:廣度優先搜索上一次已經提到,圖的遍歷一般有兩種算法,即廣度優先和深度優先。其中廣度優先搜索算法會從指定的第一個頂點開始遍歷圖,先訪問其所有的相鄰點,就像一次訪問圖的一層。其它最短路徑算法對于加權圖的最短路徑,廣度優先算法可能并不合適。 廣度優先搜索(BFS) 上一次已經提到,圖的遍歷一般有兩種算法,即廣度優先和深度優先。其中廣度優先搜索算法會從指定的第一個頂點開始遍歷圖,先訪問其所有的...
摘要:深度優先搜索上一次已經提到,圖的遍歷一般有兩種算法,即廣度優先和深度優先。用深度優先搜索算法對圖中的任務圖進行拓撲排序最終各頂點的發現和探索完成時間會保存在中。 深度優先搜索(DFS) 上一次已經提到,圖的遍歷一般有兩種算法,即廣度優先和深度優先。其中深度優先搜索算法會從第一個指定的頂點開始遍歷圖,沿著路徑直到這條路徑最后一個頂點,接著原路回退并探索下一條路徑。換句話說,它是先深度后廣...
閱讀 2609·2021-11-17 17:00
閱讀 1863·2021-10-11 10:57
閱讀 3716·2021-09-09 11:33
閱讀 911·2021-09-09 09:33
閱讀 3550·2019-08-30 14:20
閱讀 3311·2019-08-29 11:25
閱讀 2796·2019-08-26 13:48
閱讀 734·2019-08-26 11:52