圖 是由頂點的有窮非空集合和頂點之間邊的集合組成。數組
圖 是一種較線性表和樹更加複雜的數據結構。在圖形結構中,結點之間的關係能夠是任意的,圖中任意兩個數據元素之間均可能相關。微信
線性表中咱們把數據元素叫元素,樹中將數據元素節點,在圖中數據元素,咱們則稱之爲頂點。數據結構
線性表中,相鄰的數據元素之間具備線性關係,樹結構中,相鄰兩層的節點具備層次關係,而圖中,任意兩個頂點之間均可能有關係,頂點之間的邏輯關係用邊來表示,邊集能夠是空的。優化
若頂點到頂點之間的邊沒有方向,則稱這條邊爲 無向邊。 若頂點到頂點之間的邊有方向,則稱這條邊爲 有向邊,也稱爲 弧。設計
若是圖中任意兩個頂點之間的邊都是有向邊,則稱該圖爲 有向圖。 若是圖中任意兩個頂點之間的邊都是無向邊,則稱該圖爲 無向圖。指針
在無向圖中,若是任意兩個頂點之間都存在邊,則稱該圖爲 無向徹底圖。 在有向圖中,若是任意兩個頂點之間都存在方向互爲相反的兩條弧,則稱該圖爲 有向徹底圖。cdn
在圖中,若不存在頂點到其自身的邊,且同一條邊不重複出現,則稱這樣的圖爲 簡單圖。進程
有些圖的邊或弧具備與它相關的數字,這種與圖的邊或弧相關的數叫作 權。這些權能夠表示從一個頂點到另外一個頂點的距離或耗費。這種帶權的圖一般稱爲 網。it
與該頂點相關聯的總邊數稱爲 度。在有向圖中,頂點的度還可分爲出度和入度。以該頂點爲起點的邊稱爲 出度,以該頂點爲終點的邊稱爲 入度。io
從一個頂點到另外一個頂點之間的邊序列叫作 路徑,路徑上的邊或弧的數目稱爲 路徑的長度。
第一個頂點和最後一個頂點相同的路徑稱爲迴路或環。序列中頂點不重複出現的路徑稱爲簡單路徑。除了第一個頂點和最後一個頂點以外,其他頂點不重複出現的迴路,稱爲簡單迴路或簡單環。
無向圖中連通且 n 個頂點 n-1 條邊叫 生成樹。有向圖中一頂點入度爲 0 其他頂點入度爲 1 的叫 有向樹。一個有向圖由若干棵有向樹構成 生成森林。
1.鄰接矩陣
用兩個數組來表示圖。一個一維數組存儲圖中頂點信息,一個二維數組存儲圖中的邊或弧的信息。
在無向圖中,頂點到頂點之間有邊,就把二維數組裏對應的值設爲 1,不然設爲 0。若是須要知道某個頂點的度,就是鄰接矩陣某行元素之和。實際上,無向圖的邊數組是一個對稱矩陣。
從矩陣的左上角到右下角的主對角線爲軸,右上角的元與左下角相對應的元全都是相等的稱爲 對稱矩陣。
在有向圖中,邊是有方向的,根據方向分 入度 和 出度。所以,一個頂點到另外一個頂點之間有邊時二維數組對應的值設爲 1,不然爲 0。出度爲某行之和,入度爲某列之和。
若是在圖中每條邊帶權時,稱爲 網。好比計算最短路徑時,須要用到這個權值,所以須要把對應的權值存儲下來。上面二維數組中用 1 和 0 來區分頂點之間是否有邊,咱們能夠把真實的權值存儲到對應的二維數組中去,這樣就解決來存儲權值的問題。
2.鄰接表
上面的鄰接矩陣看起來是一個存儲圖不錯的方案,可是,當邊樹比較少的圖中,會浪費大量的存儲空間。這個時候就能夠變二維數組爲 一維數組 + 鏈表 來存儲對應的圖了,稱爲鄰接表。
圖中頂點用一個一維數組存儲,每一個頂點的全部鄰接點在對應一維數組後構成一個線性表,在無向圖中稱爲頂點的邊表,在有向圖中稱爲頂點做爲弧尾的出邊表。
這樣用 一維數組 + 鏈表 來存儲圖的方式叫作鄰接表。
3.十字鏈表
上面的存儲看似很完美,但有向圖有方向,咱們是以頂點爲弧尾來存儲邊表的,這樣很容易就能夠獲得每一個頂點的出度。但也有時爲了便於肯定頂點的入度或以頂點爲弧頭的弧,咱們能夠創建一個有向圖的逆鄰接表,即對每一個頂點都創建一個連接頂點爲弧頭的表。
把鄰接表與逆鄰接表結合起來的一種存儲方法稱爲 十字鏈表。
新的頂點表節點結構,分別是 data、firstin、firstout。
data 表示頂點的信息。
firstin 表示入邊表頭指針,指向該頂點的入邊表中第一個節點。
firstout 表示出邊表頭指針,指向該頂點的出邊表中的第一個節點。
新的邊表節點結構,分別是 tailvex、headvex、headlink、taillink。
tailvex 是指弧起點在頂點表的下標。
headvex 是指弧終點在頂點表中的下標。
headlink 是指入邊表指針域,指向終點相同的下一條邊。
taillink 是指邊表指針域,指向起點相同的下一條邊。
若是是網,還能夠再增長一個 weight 域來存儲權值。
十字鏈表的好處就是容易求得頂點的出度和入度。
4.鄰接多重表
十字鏈表是對有向圖的優化,能夠很容易的求得頂點的出度和入度。
在無向圖中,鄰接表主要是關注的頂點,若是是要標記或者刪除一條邊的時候,鄰接表的操做就比較麻煩了,這時候就能夠參考有向圖的優化十字鏈表了。
新的頂點表節點結構,分別是 data、firstedge。
data 表示頂點的信息。
firstin 表示第一個邊表指針,指向該頂點的邊表中第一個節點。
新的邊表節點結構,分別是 ivex、ilink、jvex、jvex。
ivex 和 jvex 是與某條邊依附的兩個頂點在頂點表中的下標。
ilink 指向依附頂點 ivex 的下一條邊,jlink 指向依附頂點 jvex 的下一條邊。
這樣的結構稱爲 鄰接多重表。鄰接多重表與鄰接表的差異,僅僅是在於同一條邊在鄰接表中用兩個節點表示,而在鄰接多重表中只有一個節點。
從圖中某一頂點出發訪遍圖中其他頂點,且使每個頂點僅被訪問一次,這一過程就叫作圖的遍歷。
對於圖的遍從來說,如何避免因迴路陷入死循環,就須要科學地設計遍歷方案,一般有兩種遍歷次序方案:它們是 深度優先遍歷 和 廣度優先遍歷。
1.深度優先遍歷
深度優先遍歷(Depth First Search),也有稱爲深度優先搜索,簡稱爲 DFS。
沿着頂點,儘量深的遍歷的分支。當頂點的所在邊都己被探尋過,遍歷將回溯到發現頂點的那條邊的起始頂點。這一過程一直進行到已發現從源頂點可達的全部頂點爲止。若是還存在未被發現的頂點,則選擇其中一個做爲源頂點並重復以上過程,整個進程反覆進行直到全部頂點都被訪問爲止。
深度優先遍歷 就像是樹的前序遍歷。
2.廣度優先遍歷
廣度優先遍歷(Breadth First Search),又稱爲廣度優先搜索,簡稱BFS。
圖的廣度優先遍歷就相似於樹的層序遍歷,就是從最上面的頂點,一層一層向下遍歷,直到遍歷全部的頂點。
圖 分爲 無向圖 和 有向圖,與該頂點相關聯的總邊數稱爲 度,有向圖中又分爲 出度 和 入度。
從一個頂點到另外一個頂點之間的邊序列叫作 路徑,路徑上的邊或弧的數目稱爲 路徑的長度。
存儲圖的結構主要有 鄰接矩陣、鄰接表、十字鏈表 和 鄰接多重表。
圖的遍歷分別爲 深度優先遍歷 和 廣度優先遍歷。
-- END
PS:
清山綠水始於塵,博學多識貴於勤。
我有酒,你有故事嗎?
微信公衆號:「清塵閒聊」。
歡迎一塊兒談天說地,聊代碼。