學習數據結構--第五章:圖(圖的存儲方法)

第五章:圖(圖的存儲方法)

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.理木客

數據結構相關知識,公衆號理木客同步更新中,歡迎關注

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章