1. 程式人生 > >圖的儲存結構(鄰接矩陣、鄰接表、十字連結串列、鄰接多重表)詳解

圖的儲存結構(鄰接矩陣、鄰接表、十字連結串列、鄰接多重表)詳解

上篇部落格講到,圖狀結構是非常複雜的結構,圖也是非常複雜的,所以圖的儲存就是一個非常重要的部分,因為我們不僅要表示頂點集,還要表示邊集,如何完整準確的表示圖呢,接下來,給大家講解四種圖的儲存方式。

一、鄰接矩陣法

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;