第五章:圖(圖的存儲方法)
1.鄰接矩陣法
下面是一個無向圖的表示,我們使用一個一維數組存放點集,使用一個二維數組存放邊集
二維數組表示邊
:行號表示其實端點,列號表示結束端點,值表示該邊是否存在,以及該邊的權重,我們稱這種二維數組表示的矩陣爲鄰接矩陣
鄰接矩陣法
:
- 結點數位n的圖G=(V,E)的鄰接矩陣A是
n*n
的(每個行號表示一個結點每個列號表示一個結點,n個結點即爲n*n) - 將G的頂點編號爲 V1,V2,V3…Vn (1,2,3…數組下標)
- 若<Vi,Vj> 存在,則
A[i][j]=1
,否則A[i][j]=0
注意有向邊和無向邊是不一樣的,有向邊 Vi---->Vj,則存放A[i][j]=1
,若無向邊Vi-------Vj,則存放A[i][j]=1、A[j][i]=1
.
有向圖鄰接矩陣:
無向圖鄰接矩陣:(關於對角線對稱)
有權重的圖:
有向邊 Vi---->Vj,則存放A[i][j]=Wi,j
,若無向邊Vi-------Vj,則存放A[i][j]=Wi,j、A[j][i]=Wi,j
.
網轉鄰接矩陣
語言實現
#define MaxvertexNum 100
typedef char VertexType; //每個結點時字符型的(類型可自行調整)
typedef int EdgeType; //可表示便是否存在、邊的權重(類型可以自行調整)
typedef struct{
VertexType Vex[MaxVertexNum];//點集數組
EdgeType Edge[MaxVertexNum][MaxVertexNum];//邊集數組
int vexnum,arcnum;//結點的數量和邊的數量
}MGraph;
鄰接矩陣法的空間複雜度位O(n^2)
2.鄰接矩陣性質
性質1:鄰接矩陣法的空間複雜度位O(n^2),適用於稠密圖
因爲無論該邊是否存在,我們都會爲其申請空間,所以稠密圖也就是邊越多的圖它的空間利用率也就越高
性質2:無向圖的鄰接矩陣爲對稱矩陣
性質3:無向圖中第 i 行(或第 i 列)非0元素(非正無窮)的個數爲第 i 個頂點的度;有向圖中第 i 行(第 i 例)非0元素(非正無窮)的個數爲第 i 個頂點的出度(入度)
設圖G的鄰接矩陣爲A,矩陣運算A^n的含義??
我們先看A^2
,首先兩個矩陣,我們知道A^2[2][5]=1*1+0*0+1*1+0*0+0*0=2
首先第一個1*1
:第一個1代表B->A,第二個1代表A->E,相乘代表B->E存在一條B->A->E的路徑,第二個1*1
:第一個1代表B->C,第二個1代表C->E,相乘代表B->E存在一條:B->C->E的路徑。
所以:A^2[2][5]=2
表示從頂點V2(B)到頂點V5(E)長度爲2的路徑有兩條。(長度爲2因爲是的A方,兩條是因爲值爲2)
現在我們再看A^3
,首先兩個矩陣,一個是A^2
,一個是A
則:A^3[2][5]=0*0+0*0+1*1+1*0+2*0=1
,首先我們知道A^2[2][3]=1表示從頂點V2->V5長度爲2的路徑只有一條
,則A^3[2][5]=1表示從頂點V2到頂 點V5長度爲3的路徑只有一條
綜上我們可知A^n[i][j]表示從頂點vi到頂點Vj長度爲n的路徑的條數
2.鄰接矩陣表
上面講解了鄰接矩陣法,對於上面的稀疏圖,我們如果採用鄰接矩陣法存儲的話,會出現很多空間的浪費即
鄰接矩陣法存儲稀疏圖會有許多空間浪費 ,對於稀疏圖我們通常採用鄰接表法存儲
鄰接表法
:爲每一個頂點建立一個單鏈表存放與它相鄰的邊
- 頂點表:採用
順序存儲
,每個數組元素存放頂點的數據和邊表的頭指針 - 邊表(出邊表):採用
鏈式存儲
,單鏈表中存放與一個頂點相鄰的所有邊,一個鏈表結點表示一條從該頂點到鏈表結點頂點的邊
3.鄰接表法
有向圖:
無向圖:
代碼實現
#define MaxVertexNum 100
//邊表
typedef struct ArcNode{
int adjvex; //下一個結點的下標
struct ArcNode *next;//指針指向下一個邊表結點
//InfoType info; //表的權重
}ArcNode;
//頂點表
typedef struct VNode{
VertexType data;//數據
ArcNode *first //指向屬於它的邊表的頭指針
}VNOode,AdjList [MaxVertexNum];//數組類型
//鄰接表
typedef struct{
AdjList vetices;//頂點表
int vexnum,arcnum;//頂點數量和邊的數量
}ALGraph;
‘
鄰接表特點
V表示頂點數量、E表示邊的數量
- 若G爲無向圖,存儲空間爲O(V+2E)
- 若G爲有向圖,存儲空間爲O(V+E)
- 鄰接表更加適用於稀疏圖
- 若G爲無向圖,則結點的度爲該結點邊表的長度
- 若G爲有向圖,則結點的出度爲該結點邊表的長度,計算入度則要遍歷整個鄰接表
- 鄰接表不唯一,邊表結點的順序根據算法和輸入的不同可以能會不同
4.鄰接矩陣VS鄰接表
5.十字鏈表
·十字鏈表
:有向圖 的一種鏈式存儲結構
我們在鄰接表中可以發現,如果尋找一個結點的出度,非常方便,直接遍歷該節點的邊表即可,但是如果想找一個結點的入度則需要遍歷整個鄰接表比較複雜,所以我們引入了十字鏈表,它無論是查詢結點的出度和入度都比較簡單。
頂點表結點
data:數據域
firstin:入邊單鏈表的頭指針
firstout:出邊單鏈表的頭指針
邊表結點
tailvex:該弧弧尾端點
headvex:該弧弧頭端點
hlink:下一個弧弧頭的指針
tlink:下一個弧弧尾的指針
info:邊的權重
代碼實現
#define MaxVertexNum 100
typedef struct ArcNode{
int tailvex,headvex;
struct ArcNode *hlink,*tlink;
//InfoType info:
}ArcNode;
typedef struct VNode{
VertexType data;
ArcNode *firstin,*firstout;
}VNode;
typedef struct{
VNode xlist[MaxVertexNum];
int vexnum, arcnum;
}GLGraph;
6.鄰接多重表
上面講的·十字鏈表
是 有向圖
的一種鏈式存儲結構,而鄰接多重表
則是針對無向圖
的一種鏈式存儲結構。
我們在鄰接表中如果想要刪除一條無向邊,我們需要找到對應的結點,然後遍歷其邊表,找到對應的邊表結點並把它刪除,這樣操作的效率比較低。由此引出鄰接多重表
ivex:該邊的第一個端點
ilink:與第一個端點相鄰的下一個邊的邊表結點的指針
jvex:該邊的第二個端點
jlink:與第二個端點相鄰的下一個邊的邊表結點的指針
info:權重(不必要)
mark:標記(不必要)
#define MaxVertexNum 100
typedef struct ArcNode{
int ivex, jvex;
struct ArcNode *ilink, *jlink;
//InfoType info;
//bool mark:
}ArcNode;
typedef struct VNode{
VertexType data;
ArcNode *firstedge;
)VNode;
typedef struct{
VNode adjmulist[MaxVertexNum];
int vexnum, arcnum;
}AMLGraph;
7.理木客
數據結構相關知識,公衆號理木客
同步更新中,歡迎關注