成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法 — 圖

yiliang / 2123人閱讀

摘要:圖關(guān)聯(lián)矩陣在關(guān)聯(lián)矩陣表示的圖中,矩陣的行表示頂點(diǎn),列表示邊。如圖,頂點(diǎn)數(shù)是,邊的數(shù)量是,用鄰接矩陣表示圖需要的空間是,而使用關(guān)聯(lián)矩陣表示圖需要的空間是。廣度優(yōu)先搜索算法數(shù)據(jù)結(jié)構(gòu)是隊(duì)列。深度優(yōu)先搜索算法數(shù)據(jù)結(jié)構(gòu)是棧。

定義

圖和散列表、二叉樹一樣,是一種非線性數(shù)據(jù)結(jié)構(gòu)。如圖1所示,圖由一系列頂點(diǎn)以及連接頂點(diǎn)的邊構(gòu)成。由一條邊連接在一起的頂點(diǎn)成為相鄰頂點(diǎn),比如A和B、A和D是相鄰的,而A和E不是相鄰的。一個(gè)頂點(diǎn)相鄰頂點(diǎn)的數(shù)量叫作度,比如A的度為3、D的度為4。路徑指相鄰頂點(diǎn)的一個(gè)連續(xù)序列,如ABEI、ACDG;簡單路徑指不包含重復(fù)頂點(diǎn)的路徑(除環(huán)外),如ADG;環(huán)指首尾頂點(diǎn)相同的路徑,如ADCA,環(huán)也屬于簡單路徑。如果圖中每兩個(gè)頂點(diǎn)之間都有路徑相連,則稱該圖是連通的。

圖1

如圖2,如果圖中的邊具有方向,稱該圖為有向圖。如果圖中的邊是雙向的,則該圖是強(qiáng)連通的,例如圖3中的C和D是強(qiáng)連通的。圖也可以是加權(quán)的,例如圖3中的每條邊都有權(quán)值。

圖2

圖3

圖可以用來解決計(jì)算機(jī)中的很多問題,比如搜索圖中的一個(gè)特定頂點(diǎn)或搜索一條特定邊,尋找圖中的一條路徑(從一個(gè)頂點(diǎn)到另一個(gè)頂點(diǎn)) ,尋找兩個(gè)頂點(diǎn)之間的最短路徑,以及環(huán)檢測。

圖的表示

圖的表示方式有多種,沒有絕對(duì)正確的表示方式,采用哪種方式取決于圖的類型和待解決的問題。這里介紹三種方式:鄰接矩陣、鄰接表、關(guān)聯(lián)矩陣。

鄰接矩陣

鄰接矩陣用一個(gè)二維數(shù)組來表示圖中頂點(diǎn)的連接情況;如果索引為i的節(jié)點(diǎn)和索引為j的節(jié)點(diǎn)連接,則array[i][j] === 1,否則array[i][j] === 0,如圖4。鄰接矩陣的缺點(diǎn)是,如果圖不是強(qiáng)連通的,矩陣中就會(huì)出現(xiàn)很多0,從而計(jì)算機(jī)需要浪費(fèi)存儲(chǔ)空間來表示根本不存在的邊。例如,即使某一頂點(diǎn)只有一個(gè)相鄰頂點(diǎn),也需要一整行來表示該頂點(diǎn)的連接情況,

圖4

鄰接表

鄰接表由圖中每個(gè)頂點(diǎn)的相鄰頂點(diǎn)的列表所組成,如圖5。只要能表示一對(duì)多的數(shù)據(jù)結(jié)構(gòu),都可以用來描述鄰接表,比如多維列表(數(shù)組)、鏈表、散列表、字典等。
在大多數(shù)情況下,鄰接表是更好的選擇,但鄰接矩陣也有其優(yōu)點(diǎn),比如要判斷頂點(diǎn)A和B是否相鄰,鄰接矩陣比鄰接表要快。

圖5

關(guān)聯(lián)矩陣

在關(guān)聯(lián)矩陣表示的圖中,矩陣的行表示頂點(diǎn),列表示邊。如圖6所示,我們使用二維數(shù)組來表示兩者之間的連通性,如果頂點(diǎn)A是邊E的入射點(diǎn),則array[A][E] === 1;否則,array[A][E] === 0。
關(guān)聯(lián)矩陣通常用于邊的數(shù)量比頂點(diǎn)少的情況下,以節(jié)省空間和內(nèi)存。如圖6,頂點(diǎn)數(shù)是5,邊的數(shù)量是6,用鄰接矩陣表示圖需要的空間是5*5=25,而使用關(guān)聯(lián)矩陣表示圖需要的空間是5*6=30。

圖6

創(chuàng)建圖類

首先首先聲明類的骨架:

function Graph() {
    var vertices = [];
    var adjList = new Dictionary();
}

其中Dictionary類的實(shí)現(xiàn)參考之前的文章字典。
我們使用數(shù)組 vertices 來存儲(chǔ)圖中所有頂點(diǎn)的名字,以及字典 adjList 來存儲(chǔ)鄰接表。字典將會(huì)使用頂點(diǎn)的名字作為鍵,鄰接頂點(diǎn)列表作為值。
接下來實(shí)現(xiàn)向圖中添加頂點(diǎn)的方法:

this.addVertex = function(v){
    vertices.push(v);
    adjList.set(v, []);
};

該方法接受頂點(diǎn) v 作為參數(shù)。我們將該頂點(diǎn)添加到頂點(diǎn)列表 vertices 中,并且在鄰接表中,設(shè)置頂點(diǎn) v 作為鍵對(duì)應(yīng)的字典值為一個(gè)空數(shù)組。
接著實(shí)現(xiàn)一個(gè)點(diǎn)到另一個(gè)點(diǎn)的連接:

this.addEdge = function(v, w){
    adjList.get(v).push(w);
    adjList.get(w).push(v);
};

這個(gè)方法接受兩個(gè)頂點(diǎn)作為參數(shù)。首先,我們通過將 w 加入到 v 的鄰接表中,添加了一條自頂
點(diǎn) v 到頂點(diǎn) w 的邊。如果是有向圖,則只需要該方法的第一行代碼就行了。我們這里要實(shí)現(xiàn)無向圖,我們需要添加一條自 w 向 v 的邊,即該方法的第二行代碼。
使用該圖類進(jìn)行簡單的測試:

var graph = new Graph();
var myVertices = ["A","B","C","D"];
for (var i=0; i

上述代碼生成圖對(duì)應(yīng)的鄰接表為:
A -> B C
B -> A D
C -> A D
D -> B C

圖的遍歷

有兩種算法可以對(duì)圖進(jìn)行遍歷:廣度優(yōu)先搜索(Breadth-First Search,BFS)和深度優(yōu)先搜索(Depth-First Search,DFS)。圖遍歷可以用來尋找特定的頂點(diǎn)或?qū)ふ覂蓚€(gè)頂點(diǎn)之間的路徑,檢查圖是否連通,檢查圖是否含有環(huán)等。
圖遍歷算法的思路是追蹤每個(gè)第一次訪問的節(jié)點(diǎn),并且追蹤有哪些節(jié)點(diǎn)還沒有被完全探索。對(duì)于兩種圖遍歷算法,都需要明確指出第一個(gè)被訪問的頂點(diǎn)。
完全探索一個(gè)頂點(diǎn)需要查看該頂點(diǎn)的每一條邊。對(duì)于每一條邊所連接的沒有被訪問過的頂點(diǎn),將其標(biāo)注為被發(fā)現(xiàn)的,并將其加進(jìn)待訪問頂點(diǎn)列表中。
我們用三種狀態(tài)來反映頂點(diǎn)的狀態(tài):

白色:表示該頂點(diǎn)還沒有被訪問。

灰色:表示該頂點(diǎn)被訪問過,但并未被探索過。

黑色:表示該頂點(diǎn)被訪問過且被完全探索過。

因?yàn)橹挥羞@三種狀態(tài),初始狀態(tài)是白色,因此每個(gè)頂點(diǎn)至多訪問兩次,這樣做能夠保證算法的效率。
廣度優(yōu)先搜索算法和深度優(yōu)先搜索算法基本上是相同的,只是待訪問頂點(diǎn)列表的數(shù)據(jù)結(jié)構(gòu)不同。
廣度優(yōu)先搜索算法:數(shù)據(jù)結(jié)構(gòu)是隊(duì)列。通過將頂點(diǎn)存入隊(duì)列中,最先入隊(duì)列的頂點(diǎn)先被探索。
深度優(yōu)先搜索算法:數(shù)據(jù)結(jié)構(gòu)是棧。通過將頂點(diǎn)存入棧中,沿著路徑探索頂點(diǎn),存在新的相鄰頂點(diǎn)就去訪問。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/91883.html

相關(guān)文章

  • CSS技巧

    摘要:技巧使你的更加專業(yè)這是上關(guān)于技巧的一篇譯文,另外你也可以在本項(xiàng)目看到原文。列舉了一些很實(shí)用的技巧,比如給空內(nèi)容的標(biāo)簽添加內(nèi)容,逗號(hào)分隔列表等等。排序算法看源碼,把它背下來吧排序算法的封裝。主要幫助初學(xué)者更好的掌握排序算法的實(shí)現(xiàn)。 成為專業(yè)程序員路上用到的各種優(yōu)秀資料、神器及框架 成為一名專業(yè)程序員的道路上,需要堅(jiān)持練習(xí)、學(xué)習(xí)與積累,技術(shù)方面既要有一定的廣度,更要有自己的深度。 Java...

    DangoSky 評(píng)論0 收藏0
  • CSS技巧

    摘要:技巧使你的更加專業(yè)這是上關(guān)于技巧的一篇譯文,另外你也可以在本項(xiàng)目看到原文。列舉了一些很實(shí)用的技巧,比如給空內(nèi)容的標(biāo)簽添加內(nèi)容,逗號(hào)分隔列表等等。排序算法看源碼,把它背下來吧排序算法的封裝。主要幫助初學(xué)者更好的掌握排序算法的實(shí)現(xiàn)。 成為專業(yè)程序員路上用到的各種優(yōu)秀資料、神器及框架 成為一名專業(yè)程序員的道路上,需要堅(jiān)持練習(xí)、學(xué)習(xí)與積累,技術(shù)方面既要有一定的廣度,更要有自己的深度。 Java...

    zgbgx 評(píng)論0 收藏0
  • 優(yōu)秀程序員都應(yīng)該學(xué)習(xí)的 GitHub 上開源的數(shù)據(jù)結(jié)構(gòu)算法項(xiàng)目

    摘要:強(qiáng)烈推薦上值得前端學(xué)習(xí)的數(shù)據(jù)結(jié)構(gòu)與算法項(xiàng)目,包含圖的演示過程與視頻講解。該倉庫包含了多種基于的算法與數(shù)據(jù)結(jié)構(gòu),提供進(jìn)一步閱讀的解釋和鏈接。數(shù)據(jù)結(jié)構(gòu)和算法必知必會(huì)的個(gè)代碼實(shí)現(xiàn)。 showImg(https://segmentfault.com/img/bVbvpYZ); 前言 算法為王。想學(xué)好前端,先練好內(nèi)功,內(nèi)功不行,就算招式練的再花哨,終究成不了高手;只有內(nèi)功深厚者,前端之路才會(huì)走得...

    cheukyin 評(píng)論0 收藏0
  • 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)算法 — 廣度優(yōu)先搜索算法

    摘要:廣度優(yōu)先搜索上一次已經(jīng)提到,圖的遍歷一般有兩種算法,即廣度優(yōu)先和深度優(yōu)先。其中廣度優(yōu)先搜索算法會(huì)從指定的第一個(gè)頂點(diǎn)開始遍歷圖,先訪問其所有的相鄰點(diǎn),就像一次訪問圖的一層。其它最短路徑算法對(duì)于加權(quán)圖的最短路徑,廣度優(yōu)先算法可能并不合適。 廣度優(yōu)先搜索(BFS) 上一次已經(jīng)提到,圖的遍歷一般有兩種算法,即廣度優(yōu)先和深度優(yōu)先。其中廣度優(yōu)先搜索算法會(huì)從指定的第一個(gè)頂點(diǎn)開始遍歷圖,先訪問其所有的...

    eternalshallow 評(píng)論0 收藏0
  • 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)算法 — 深度優(yōu)先搜索算法

    摘要:深度優(yōu)先搜索上一次已經(jīng)提到,圖的遍歷一般有兩種算法,即廣度優(yōu)先和深度優(yōu)先。用深度優(yōu)先搜索算法對(duì)圖中的任務(wù)圖進(jìn)行拓?fù)渑判蜃罱K各頂點(diǎn)的發(fā)現(xiàn)和探索完成時(shí)間會(huì)保存在中。 深度優(yōu)先搜索(DFS) 上一次已經(jīng)提到,圖的遍歷一般有兩種算法,即廣度優(yōu)先和深度優(yōu)先。其中深度優(yōu)先搜索算法會(huì)從第一個(gè)指定的頂點(diǎn)開始遍歷圖,沿著路徑直到這條路徑最后一個(gè)頂點(diǎn),接著原路回退并探索下一條路徑。換句話說,它是先深度后廣...

    李增田 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<