圖的存儲結構

原文鏈接http://blog.csdn.net/midgard/article/details/4076619

圖,無向圖G = (V, E)有向圖 G = <V, E> V是點集vertex, E是邊集edge
圖通常有兩種存儲方法。
  • 鄰接矩陣, 多用於稠密圖,記錄每兩個頂點之間邊的信息。空間複雜度是O(|V|2);通常實際問題稠密圖情況很少。
  • 鄰接表, 是表示圖的標準方法,尤其對於稀疏圖節省很多存儲空間,空間複雜度是O(|E|+|V|). 對於每個頂點,使用一個表存放所有鄰接的頂點。
鄰接矩陣容易理解就不介紹了,鄰接表實現方法:
(1)使用vector或list
(2)使用map,將key設爲頂點,值設爲鄰接表。
(3)使用Vertex類,頂點即爲Vertex的實例,將鄰接表作爲Vertex的成員函數。
下面一步一步介紹如何用代碼實現鄰接表結構來存儲圖,主要體會爲什麼需要這些信息。
首先,從鄰接表的定義中直觀的看出需要有頂點信息,對於每個頂點一定存儲了數據信息,鄰接頂點信息。而對於鄰接頂點結構,一定存儲了next鄰接頂點信息。即:
struct adjVertexNode
{
adjVertexNode* next;
}
struct VertexNode
{
char* data;//以結點存儲的信息爲字符爲例。
adjVertexNode* list; //鄰接點鏈表。
}
一個圖結構便可以由結點數組組成。考慮到數組不能用變量聲明大小。所以預先給定一個足夠大的數組。當然也可以用vector,List實現,那是後話了。同時圖必須要包含頂點數量信息。
#define MAX_VERTEX_NUM 20
struct Graph
{
VertexNode VertexNode[MAX_VERTEX_NUM];
int vertexNum;
}
以上,是我們嘗試構建一個圖的存儲結構必須,也是一定應該會想到的信息。
接下來,對於adjVertexNode結構體, 由於它明顯是個鏈表,很容易會考慮裏面是不是應該有數據信息呢?否則只有一個鏈沒有意義。
於是很容易想到寫成存鄰接頂點數據信息:
struct adjVertexNode
{
char* data;
adjVertexNode* next;
}
而恰恰這是最容易出現的錯誤寫法!!!事實上這個數據信息已在頂點VertexNode結構體中體現了,完全沒有必要這樣重複寫出來。
回過頭仔細看一下定義:對於每個頂點,使用一個表存放所有鄰接的頂點。也就是說,存放的數據一定是標識鄰接頂點的信息。但又不能重複存放定點數據信息。
因爲一個圖鄰接表表示法需要一個存儲頂點的數組,所以這裏應該存放頂點位置信息,也就是每個頂點在頂點數組中的位置信息。即:
struct adjVertexNode
{
int adjVertexPosition;
adjVertexNode* next;
}
務必要理解這一點,如果還是有點暈,那先記住他,到後面實現拓撲排序時,會看到爲什麼要存儲位置信息。
另外,對於拓撲排序,起始點是從一個入度爲0的頂點開始,所以入度信息必須包含在頂點結構體中。於是:
struct VertexNode
{
char* data;//以結點存儲的信息爲字符爲例。
adjVertexNode* list; //鄰接點鏈表。
int indegree;
}
至此,得到了一組圖需要的較爲完整的結構體信息,至少完成拓撲排序所需要的信息足夠了。
#define MAX_VERTEX_NUM 20
struct adjVertexNode
{
int adjVertexPosition;
adjVertexNode* next;
}
struct VertexNode
{
char* data;//以結點存儲的信息爲字符爲例。
adjVertexNode* list; //鄰接點鏈表。
int indegree;
}
struct Graph
{
VertexNode VertexNode[MAX_VERTEX_NUM];
int vertexNum;
}
還有一些其他信息,比如邊上的權值(可以存儲在adjVertexNode中),圖的邊數,類型(可以存儲在Graph中),這裏沒有添加,主要是避免混淆。當真正理解每個元素信息爲什麼需要時再做擴展。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章