圖的儲存結構(鄰接矩陣、鄰接表、十字連結串列、鄰接多重表)詳解
上篇部落格講到,圖狀結構是非常複雜的結構,圖也是非常複雜的,所以圖的儲存就是一個非常重要的部分,因為我們不僅要表示頂點集,還要表示邊集,如何完整準確的表示圖呢,接下來,給大家講解四種圖的儲存方式。
一、鄰接矩陣法
1、定義
我們用一個二維陣列存放頂點間關係(邊或弧)的資料,這個二維陣列稱為鄰接矩陣。鄰接矩陣又分為有向圖鄰接矩陣和無向圖鄰接矩陣。
設G=(V,E)是一個圖,其中V={v1,v2,…,vn},若(Vi,Vj)∈E,則A[ i,j ] = 1,否則A[ i,j ] = 0;即下圖
對於帶權圖來說,可以將A[ i,j ] 用來儲存權值,如果兩結點無連線,用無窮表示。
2、特點
無向圖的鄰接矩陣對稱且唯一。
有向圖的鄰接矩陣的第 i 行非零元素個數為第 i 個頂點的出度;第 j 列非零元素個數為第 j 個頂點的入度。
稠密圖更適合用鄰接矩陣儲存。
3、程式碼
#define MaxVertexNum 100 //Maximum value of the vertex number typedef char VertexType; //the type of vertex typedef int EdgeType; // the type of wight on the edge in weighted graph 帶權圖中邊上的權值的型別 // the graph are storaged by adjacency matrix 鄰接矩陣儲存圖 typedef struct { VertexType Vex[MaxVertexNum]; EdgeType Edge[MaxVertexNum][MaxVertexNum]; // adjacency matrix int vexNum, arcNum; //current vertex number and arc of graph }MGraph;
二、鄰接表法
1、定義
鄰接表,儲存方法跟樹的孩子連結串列示法相類似,是一種順序分配和鏈式分配相結合的儲存結構。如這個表頭結點所對應的頂點存在相鄰頂點,則把相鄰頂點依次存放於表頭結點所指向的單向連結串列中。如下圖是無向圖的鄰接表法表示
2、特點
鄰接表法是為了節省儲存空間引入的,對於稀疏圖,相對於鄰接矩陣,無需耗費大量儲存空間,對於有向圖來說,還有逆鄰接表的概念,如下圖,是有向圖的鄰接表,表中指向方向與圖本身指向方向相同,所以有向圖的鄰接表可以得到圖的出度,逆鄰接表可以得到圖的入度。
3、程式碼
#define MaxVertexNum 100 //Maximum value of the vertex number //the graph are storaged by adjacency list typedef struct ArcNode { int adjvex; // the location of the vertex which was pointed by arc struct ArcNode *next; }ArcNode; typedef struct VNode { VertexType data; ArcNode *first; }VNode,AdjList[MaxVertexNum]; typedef struct { AdjList vertices; // adjacency list int vexNum, arcNum; // current vertex number and arc of graph }ALGraph;
三、十字連結串列
1、定義
十字連結串列(Orthogonal List)是有向圖的另一種鏈式儲存結構。該結構可以看成是將有向圖的鄰接表和逆鄰接表結合起來得到的。用十字連結串列來儲存有向圖,可以達到高效的存取效果。同時,程式碼的可讀性也會得到提升。
2、特點
十字連結串列容易找到vi為尾的弧,也容易找到vi為頭的弧,因而容易求得頂點的入度與出度。
圖的十字連結串列表示不唯一,但一個十字連結串列表示一個確定的圖。
3、程式碼
#define MaxVertexNum 100 //Maximum value of the vertex number
// the graph are storaged by orthogonal list
typedef struct ArcNode {
int tailvex, headvex; // the location of the vertex which was pointed by arc
struct ArcNode *hlink, *tlink;
}ArcNode;
typedef struct VNode {
VertexType data;
ArcNode *firstIn, *firshOut;
}VNode;
typedef struct {
VNode xList[MaxVertexNum]; // adjacency list
int vexNum, arcNum; // current vertex number and arc of graph
}GLGraph;
四、鄰接多重表
1、引入
十字連結串列是對有向圖的儲存結構進行另一個角度的表示,同樣的鄰接多重表是對無向圖的另一種表示方法。
如果我們在無向圖的應用中,更加關注圖的頂點,那麼鄰接表是不錯的選擇,但如果我們更關注邊的操作,比如對已訪問過的邊做標記,刪除某一條邊等操作,那就意味著需要找到這條邊的兩個邊表結點進行操作,若要刪除某條邊,需要對鄰接表結構中相關的兩個結點進行刪除,顯然這是比較繁瑣的。
2、特點
在鄰接多重表中,每一條邊用一個結點來表示,結構如下:
其中,mark為標誌域,用於標記該條邊是否被訪問;ivex與jvex為該條邊的兩個頂點的位置;ilink為指向下一條依附於頂點ivex的邊,jlink為指向下一條依附於頂點jvex的邊;info為指向和邊相關的各種資訊的指標域。
每個頂點也用一個結點表示,該結點由如下兩個域組成:
3、程式碼
#define MaxVertexNum 100 //Maximum value of the vertex number
// the graph are storaged by adjacency multiple tables
typedef struct ArcNode {
bool mark;
int ivex, jvex;
struct ArcNode *ilink, *jlink;
}ArcNode;
typedef struct VNode {
VertexType data;
ArcNode *firstedgr;
}VNode;
typedef struct {
VNode agjmuList[MaxVertexNum];
int vexNum, arcNum;
}AMLGraph;