1. 程式人生 > >圖論基礎(自認為很全)

圖論基礎(自認為很全)

# 什麼是圖 在一個社交網路中,每個帳號和他們之間的關係構成了一張巨大的網路,就像下面這張圖: ![在這裡插入圖片描述](https://imgconvert.csdnimg.cn/aHR0cDovL3Jlcy5qaXN1YW5rZS5jb20vaW1nL3VwbG9hZC8yMDE2MDQwNy80MGNiY2FhNjU2OGNhY2VkMjkwNTQyMjRlZmQ2OTE0MDNmYWVhNjU2LnBuZw?x-oss-process=image/format,png#pic_center) 那麼在電腦中,我們要用什麼樣的資料結構來儲存這個網路呢?這個網路需要用一個之前課程裡未提到過的資料結構,也就是接下來要講解的**圖**結構來儲存。 到底什麼是圖?圖是由一系列頂點和若干連結頂點集合內兩個頂點的邊組成的資料結構。數學意義上的圖,指的是由一系列點與邊構成的集合,這裡我們只考慮有限集。通常我們用 *G=(V,E)* 表示一個圖結構,其中*V*表示點集,*E*表示邊集。 在頂點集合所包含的若干個頂點之間,可能存在著某種兩兩關係——如果某兩個點之間的確存在這樣的關係的話,我們就在這兩個點之間連邊,這樣就得到了邊集的一個成員,也就是一條邊。對應到社交網路中,頂點就是網路中的使用者,邊就是使用者之間的好友關係。 如果用邊來表示好友關係的話,對於微信這種雙向關注的社交網路沒有問題,但是對於微博這種單向關注的要如何表示呢? 於是引出了兩個新的概念:有向邊和無向邊。 簡而言之,一條有向邊必然是從一個點指向另一個點,而相反方向的邊在有向圖中則不一定存在;而有的時候我們並不在意構成一條邊的兩個頂點具體誰先誰後,這樣得到的一條邊就是無向邊。就像在微信中,*A*是*B*的好友,那*B*也一定是*A*的好友,而在微博中,*A*關注*B*並不意味著B也一定關注*A*。 對於圖而言,如果圖中所有邊都是無向邊,則稱為無向圖,反之稱為有向圖。 簡而言之,無向圖中的邊是“好友”,而有向圖中的邊是“關注”。一般而言,我們在資料結構中所討論的圖都是有向圖,因為有向圖相比無向圖更具有代表性。 實際上,無向圖可以由有向圖來表示。如果*AB*兩個點之間存在無向邊的話,那用有向圖也可以表示為*AB*兩點之間同時存在*A*到*B*與*B*到*A*兩條有向邊。 仍然以社交網路舉例:雖然微博中並不存在明確定義的好友關係,但是一般情況下,如果你和另一個 ID 互相關注的話,那麼我們也可以近似認為,你和 TA 是好友。 我們來形式化地定義一下圖:圖是由頂點集合(簡稱**點集**)和頂點間的邊(簡稱**邊集**)組成的資料結構,通常用*G(V,E)*來表示。其中點集用*V(G)* 來表示,邊集用 *E(G)* 來表示。在**無向圖**中,邊連線的兩個頂點是無序的,這些邊被稱為**無向邊**。例如下面這個無向圖*G*,其點集*V(G)={1,2,3,5,6}*,邊集為*E(G)={(1,2),(2,3),(1,5),(2,6),(5,6)}*。 ![在這裡插入圖片描述](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yZXMuamlzdWFua2UuY29tL2ltZy91cGxvYWQvMjAxNzA0MjUvOTJjZTlhYjcyNThjNDJmNjI0MjdmZWVhNDA5NDU3Nzk4NzcyOWZlNS5wbmc?x-oss-process=image/format,png#pic_center) 而在有向圖中,邊連線的兩個頂點之間是有序的。箭頭的方向就表示有向邊的方向。 例如下面這張有向圖*G'*: ![在這裡插入圖片描述](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yZXMuamlzdWFua2UuY29tL2ltZy91cGxvYWQvMjAxNzA0MjUvOGUzODExN2ViZmY0ZDE2NDBmMThiODBmMDI3ODc1NDY0ODE4NGMwOS5wbmc?x-oss-process=image/format,png#pic_center) 其點集*V(G′)={1,2,3,5,6}*,邊集為*E(G′)={(1,2),(2,3),(2,6),(6,5),(1,5)}*。對於每條邊 *(u,v)* ,我們稱其為從u到v的一條有向邊,*u*是這條有向邊的**起點**,*v* 是這條有向邊的**終點**。注意在有向圖中,*(u,v)* 和 *(v,u)* 是不同的兩條有向邊。 # 圖的分類 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200906124504939.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1JpY2hhcmRfMTEwMQ==,size_16,color_FFFFFF,t_70#pic_center) ![在這裡插入圖片描述](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yZXMuamlzdWFua2UuY29tL2ltZy91cGxvYWQvMjAxNzA0MjUvYjkzMjA0YmJmMzYwZTg1YjA1ZTk5N2NhODVmZjA0ZDBmNmZjZmQ1Mi5wbmc?x-oss-process=image/format,png#pic_center) 對於一個圖,如果以任意一個點為起點,在圖上沿著邊走都可以到達其他所有點(有向圖必須沿有向邊的方向),那麼這個圖就是**連通圖**。顯然完全圖一定是連通圖。 # 度 ## 定義 在無向圖中,頂點的**度**是指某個頂點連出的邊數。例如在下圖中,頂點 *b* 的度數為3,頂點 *a* 的度數為4。 ![在這裡插入圖片描述](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yZXMuamlzdWFua2UuY29tL2ltZy91cGxvYWQvMjAxNzA0MjUvYWI3YjBiNDk5MjE4MTAwOTE4ZjMxMTNmZWM1ZmVlMTVhM2U3ZjE1OS5wbmc?x-oss-process=image/format,png#pic_center) 在有向圖中,和度對應的是**入度**和**出度**這兩個概念。頂點的入度是指以該頂點為終點的有向邊數量;頂點的出度是指以頂點為起點的有向邊數量。需要注意的是,在有向圖裡,頂點是沒有**度**的概念的。例如在下圖中,頂點 *a* 的入度為1,出度為3;頂點 *c* 的入度為2,出度為2。 ![在這裡插入圖片描述](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yZXMuamlzdWFua2UuY29tL2ltZy91cGxvYWQvMjAxNzA0MjUvNjJmZDFlMjliZGM3NmM4YTBlNzE1OGMxZDM3Y2ZkZWNhMzI5NzdiMi5wbmc?x-oss-process=image/format,png#pic_center) ## 度的性質 在無向圖或有向圖中,頂點的度數總和為邊數的兩倍,即: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200906124323452.png#pic_center) 而在有向圖中,有一個很明顯的性質就是,**入度等於出度**。 | | | | | **無向圖度數統計** ```c #include