圖的定義
圖(Graph)是由頂點的有窮非空集合和頂點之間邊的集合組成,通常表示為:G(V,E),其中,G表示一個圖,V是圖G中頂點的集合,E是圖G中邊的集合。
網絡中的點通常稱為節點(Node);圖中的點則常稱為頂點(Vertex)
線性表中數據元素叫做元素;樹中將數據元素叫做結點;在圖中數據元素叫做頂點(Vertex)
無向邊
若頂點\(V_i\)到\(V_j\)之間的邊沒有方向,則稱這條邊為無向邊(Edge),用無序偶對(\(V_i\),\(V_j\))表示。簡化寫成\(e_{ij}\)
無向圖
如果圖中任意兩個頂點之間的邊都是無向邊,則稱該圖為無向圖(Undirected graphs)。
Code Implementation(Python)
# 需要導入networkx、matplotlib庫
import networkx as nx
import matplotlib.pyplot as plt
# 創建對象
G = nx.Graph()
V = ["V1", "V2", "V3", "V4", "V5"] # 一個元組
# 添加地頂點
G.add_nodes_from(V)
# 通過添加list來添加多條邊
G.add_edges_from([("V1", "V2"), ("V1", "V3"), ("V1", "V5"), ("V2", "V5"), ("V2", "V4"), ("V2", "V3"),
("V3", "V4")])
# circular_layout:表示節點在一個圓環上均勻分布
pos = nx.circular_layout(G)
nx.draw(G,
pos=pos,
with_labels=True, # 節點是否帶標簽,默認True
node_size=800, # 節點大小,默認300
node_color='#66CCFF', # 節點顏色,默認red
font_color='white', # 節點標簽的字的顏色,默認黑色
node_shape='o', # 節點形狀,默認’o’
alpha=1, # 透明度,默認1,不透明
edge_color='#CCFFFF', # 邊的顏色,默認黑色
width=3, # 邊的寬度,默認1
style='solid', # 邊的樣式,默認為實線,可選擇solid、dashed、dotted、dashdot
font_size=15 # 字體大小,默認12
)
# 添加邊的屬性說明
edge_labels = {
("V1", "V2"): "e12",
("V1", "V3"): "e13",
("V1", "V5"): "e15",
("V2", "V5"): "e25",
("V2", "V4"): "e24",
("V2", "V3"): "e23",
("V3", "V4"): "e34"
}
nx.draw_networkx_edge_labels(G,
pos,
edge_labels=edge_labels,
font_color="black" # 屬性說明的字體顏色
)
plt.show()
上圖就是一個無向圖。
- 由於是無向的,則有 \(e_{ij}\)=\(e_{ji}\)
即頂點\(V_1\)到頂點\(V_2\)的邊,既可以寫成\(e_{12}\),也可以寫成 \(e_{21}\) - 上圖可以表示為G(V,E)
其中頂點集合V={\(V_1,V_2,V_3,V_4,V_5\)},邊集合E={\((V_1,V_2),(V_1,V_3),(V_1,V_5),(V_2,V_5),(V_2,V_4),(V_2,V_3),(V_3,V_4)\)}
有向邊
若頂點\(V_i\)到\(V_j\)之間的邊有方向,則稱這條邊為有向邊(Edge),也稱為弧(Arc),用有序偶對<\(V_i\),\(V_j\)>表示,\(V_i\)稱為弧尾(Tail),\(V_j\)稱為弧頭(Head)
有向圖
如果圖中任意兩個頂點之間的邊都是有向邊,則稱該圖為無向圖(Directed graphs)。
Code Implementation(Python)
# 需要導入networkx、matplotlib庫
import networkx as nx
import matplotlib.pyplot as plt
# 創建對象
G = nx.DiGraph()
V = ["V1", "V2", "V3", "V4", "V5"] # 一個元組
# 添加地頂點
G.add_nodes_from(V)
# 通過添加list來添加多條邊
G.add_edges_from([("V1", "V2"), ("V1", "V3"), ("V1", "V5"), ("V2", "V5"), ("V2", "V4"), ("V2", "V3"),
("V3", "V4")])
# circular_layout:表示節點在一個圓環上均勻分布
pos = nx.circular_layout(G)
nx.draw(G,
pos=pos,
with_labels=True, # 節點是否帶標簽,默認True
node_size=800, # 節點大小,默認300
node_color='#66CCFF', # 節點顏色,默認red
font_color='white', # 節點標簽的字的顏色,默認黑色
node_shape='o', # 節點形狀,默認’o’
alpha=1, # 透明度,默認1,不透明
edge_color='#CCFFFF', # 邊的顏色,默認黑色
width=3, # 邊的寬度,默認1
style='solid', # 邊的樣式,默認為實線,可選擇solid、dashed、dotted、dashdot
font_size=15, # 字體大小,默認12
arrowstyle="->", # 指定箭頭樣式
arrowsize=20 # 指定箭頭大小
)
# 添加邊的屬性說明
edge_labels = {
("V1", "V2"): "e12",
("V1", "V3"): "e13",
("V1", "V5"): "e15",
("V2", "V5"): "e25",
("V2", "V4"): "e24",
("V2", "V3"): "e23",
("V3", "V4"): "e34"
}
nx.draw_networkx_edge_labels(G,
pos,
edge_labels=edge_labels,
font_color="black" # 屬性說明的字體顏色
)
plt.show()
上圖就是一個有向圖。
- 由於是有向的,則有 \(e_{ij}\)≠\(e_{ji}\)
即頂點\(V_1\)到頂點\(V_2\)的邊是有向邊,即弧,\(V_1\)是弧尾,\(V_2\)是弧頭,<\(V_1\),\(V_2\)>表示弧,注意不能寫成<\(V_2\),\(V_1\)> - 上圖可以表示為G(V,E)
其中頂點集合V={\(V_1,V_2,V_3,V_4,V_5\)},邊集合E={\(<V_1,V_2>,<V_1,V_3>,<V_1,V_5>,<V_2,V_5>,<V_2,V_4>,<V_2,V_3>,<V_3,V_4>\)}
無向完全圖
在無向圖中,如果任意兩個頂點之間都存在邊,則稱該圖為無向完全圖。
含有n個頂點的無向完全圖有\(\frac{n×(n-1)}{2}\)條邊
下圖就是無向完全圖,因為每個頂點都要與除它以外的頂點連線,頂點A與BCD三個頂點連線,共有四個頂點,自然是4×3,但由於頂點A與頂點B連線后,計算B與A連線就是重復,因此要整體除以2,共有6條邊。
有向完全圖
在有向圖中,如果任意兩個頂點之間都存在方向互為相反的兩條弧,則稱該圖為有向完全圖。
含有n個頂點的有向完全圖有\(n× (n-1)\)條邊
對於具有n個頂點和e條邊數的圖,無向圖0≤e≤\(\frac{n×(n-1)}{2}\),有向圖0≤e≤\(n (n-1)\)。
稀疏圖、稠密圖、權、網
有很少條邊或弧的圖稱為稀疏圖,反之稱為稠密圖。這里稀疏和稠密是模糊的概念,都是相對而言的。
有些圖的邊或弧具有與它相關的數字,這種與圖的邊或弧相關的數叫做權(Weight)。這些權可以表示從一個頂點到另一個頂點的距離或耗費。
這種帶權的圖通常稱為網(Network)。下圖就是一張帶權的圖,即標識中國四大城市的直線距離的網,此圖中的權就是兩地的距離。
子圖
假設有兩個圖G= (V,E) 和 G'= (\(V^',E^‘),如果V^'被包含於V且E^'被包含於E,則稱G^'為G的\)子圖(Subgraph)
如下圖帶底紋的圖均為左側無向圖與有向圖的子圖。
對於上圖中的無向圖。頂點V的度(Degree)是和V相關聯的邊的數目,記為TD (v)。
- 頂點A與B互為鄰接點,邊(A,B)依附於頂點A與B上,頂點A的度為3。而此圖的邊數是5,各個頂點度的和=3+2+3+2=10,推敲后發現,邊數其實就是各頂點度數和的一半,多出的一半是因為重復兩次記數。簡記之:
\[e = \frac{1}{2}\sum_{i=1}^{n} TD(V_i) \]
對於上圖中的有向圖。以頂點V為頭的弧的數目稱為V的入度(InDegree),記為ID(v);以V為尾的弧的數目稱為V的出度(OutDegree),記為OD(v);頂點V的度為 TD(v)=ID (v)+OD (v)。
- 頂點A的入度是2(從B到A的弧,從C到A的弧),出度是1(從A到D的弧),所以頂點A的度為2+1=3。此有向圖的弧有4條,而各頂點的出度和=1+2+1+0=4,各頂點的入度和=2+0+1+1=4。所以得到:
\[e = \sum_{i=1}^{n} ID(V_i)= \sum_{i=1}^{n} OD(V_i) \]
路徑長度
路徑的長度是路徑上的邊或弧的數目。
回路或環、簡單路徑、簡單回路或簡單環
第一個頂點到最后一個頂點相同的路徑稱為回路或環(Cyce)。序列中頂點不重復出現的路徑稱為簡單路徑。
除了第一個頂點和最后一個頂點之外,其余頂點不重復出現的回路,稱為簡單回路或簡單環。
下圖兩個圖的粗線都構成環,左側的環因第一個頂點和最后一個頂點都是B,且C、D、A 沒有重復出現,因此是一個簡單環。而右側的環,由於頂點C的重復,它就不是簡單環了。
連通圖相關術語
連通圖
在無向圖G中,如果從頂點V到頂點\(V^’\)有路徑,則稱V和\(V^’\)是連通的。
如果對於圖中任意兩個頂點\(V_i\)、\(V_j\)∈E, \(V_i\)和\(V_j\)都是連通的,則稱G是連通圖(ConnectedGraph)。
下圖的圖1,它的頂點A到頂點B、C、D 都是連通的,但顯然頂點A與頂點E或F就無路徑,因此不能算是連通圖。圖2,頂點A、B、C、D相互都是連通的,所以它本身是連通圖。
連通分量
無向圖中的極大連通子圖稱為連通分量。注意連通分量的概念,它強調:
- 要是子圖;
- 子圖要是連通的;
- 連通子圖含有極大頂點數;
- 具有極大頂點數的連通子圖包含依附於這些頂點的所有邊。
下圖的圖1是一個無向非連通圖。但是它有兩個連通分量,即圖2和圖3。而圖4,盡管是圖1的子圖,但是它卻不滿足連通子圖的極大頂點數(圖2滿足)。因此它不是圖1的無向圖的連通分量。
強連通圖、強連通分量
在有向圖G中,如果對於每一對\(V_i、V_j ∈ V、V_i≠V_j ,從V_i到V_j 和從V_j 到V_i 都\)存在路徑,則稱G是強連通圖。
有向圖中的極大強連通子圖稱做有向圖的強連通分量。
例如下圖,圖1並不是強連通圖,因為頂點A到頂點D存在路徑,而D到A就不存在。圖2就是強連通圖,而且顯然圖2是圖1的極大強連通子圖,即是它的強連通分量。
生成樹
一個連通圖的生成樹是一個極小的連通子圖,它含有圖中全部的n個頂點,但只有足以構成一棵樹的n-1條邊。
比如下圖的圖1是一普通圖,但顯然它不是生成樹,當去掉兩條構成環的邊后,比如圖2或圖3,就滿足n個頂點n-1條邊且連通的定義了。它們都是一棵生成樹。
從這里也可知道,如果一個圖有n個頂點和小於n-1條邊,則是非連通圖,如果它多於n-1邊條,必定構成一個環,因為這條邊使得它依附的那兩個頂點之間有了第二條路徑。比如圖2和圖3,隨便加哪兩頂點的邊都將構成環。不過有n-1條邊並不一定是生成樹,比如圖4。
有向樹、生成森林
如果一個有向圖恰有一個頂點的入度為0,其余頂點的入度均為1,則是一棵有向樹。
對有向樹的理解比較容易,所謂入度為О其實就相當於樹中的根結點,其余頂點入度為1就是說樹的非根結點的雙親只有一個。一個有向圖的生成森林由若干棵有向樹組成,含有圖中全部頂點,但只有足以構成若干棵不相交的有向樹的弧。
如下圖的圖1是一棵有向圖。去掉一些弧后,它可以分解為兩棵有向樹,如圖2和圖3,這兩棵就是圖1有向圖的生成森林。
總結
- 圖按照有無方向分為無向圖和有向圖。無向圖由頂點和邊構成,有向圖由頂點和弧構成。弧有弧尾和弧頭之分。
- 圖按照邊或弧的多少分稀疏圖和稠密圖。如果任意兩個頂點之間都存在邊叫完全圖,有向的叫有向完全圖。若無重復的邊或頂點到自身的邊則叫簡單圖。
- 圖中頂點之間有鄰接點、依附的概念。無向圖頂點的邊數叫做度,有向圖頂點分為入度和出度。
- 圖上的邊或弧上帶權則稱為網。
- 圖中頂點間存在路徑,兩頂點存在路徑則說明是連通的,如果路徑最終回到起始點則稱為環,當中不重復叫簡單路徑。若任意兩頂點都是連通的,則圖就
- 連通圖,有向則稱強連通圖。圖中有子圖,若子圖極大連通則就是連通分量,有向的則稱強連通分量。
- 無向圖中連通且n個頂點n-1條邊叫生成樹。有向圖中一頂點入度為0其余頂點入度為1的叫有向樹。一個有向圖由若干棵有向樹構成生成森林。
參考資料:
[1]程傑.大話數據結構[M].清華大學出版社:北京,2011.