圖的存儲結構之鄰接表

連通圖:即任意兩個點之間都間接或直接地至少有一條路徑。


對於圖來說,鄰接矩陣是不錯的一種圖存儲結構,但是我們也發現,對於邊數相對頂點較少的圖,這種結構是存在對存儲空間的極大浪費的。因此我們考慮另外一種存儲結構方式:鄰接表(Adjacency List),即數組與鏈表相結合的存儲方法。

鄰接表的處理方法是這樣的。

1、圖中頂點用一個一維數組存儲,另外,對於頂點數組中,每個數據元素還需要存儲指向第一個鄰接點的指針,以便於查找該頂點的邊信息。

2、圖中每個頂點vi的所有鄰接點構成一個線性表,由於鄰接點的個數不定,所以用單鏈表存儲,無向圖稱爲頂點vi的邊表,有向圖稱爲頂點vi作爲弧尾的出邊表。

例如圖7-4-6就是一個無向圖的鄰接表結構。


若是有向圖,鄰接表的結構是類似的,如圖7-4-7,以頂點作爲弧尾來存儲邊表容易得到每個頂點的出度,而以頂點爲弧頭的表容易得到頂點的入度,即逆鄰接表。


對於帶權值的網圖,可以在邊表結點定義中再增加一個weight的數據域,存儲權值信息即可,如圖7-4-8所示。


下面示例無向圖的鄰接表創建:(改編自《大話數據結構》)

可以直接用vector實現,爲每個頂點創建一個vector來存儲他的鄰接點的信息,新加入一個鄰接點時直接將這個點的信息push_back就行了。 可以在剛開始時定義一個全局vector<node> store[N]數組。N爲邊的個數。




 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

#include<iostream>
using namespace std;

#define MAXVEX 100 /* 最大頂點數,應由用戶定義 */
typedef char VertexType; /* 頂點類型應由用戶定義 */
typedef int EdgeType; /* 邊上的權值類型應由用戶定義 */

typedef struct EdgeNode/* 邊表結點  */
{
    int adjvex;/* 鄰接點域,存儲該頂點對應的下標 */
    EdgeType weight;/* 用於存儲權值,對於非網圖可以不需要 */
    struct EdgeNode *next; /* 鏈域,指向下一個鄰接點 */
} EdgeNode;

typedef struct VextexNode/* 頂點表結點 */
{
    VertexType data;/* 頂點域,存儲頂點信息 */
    EdgeNode *firstedge;/* 邊表頭指針 */
} VextexNode, AdjList[MAXVEX];

typedef struct
{
    AdjList adjList;
    int numNodes, numEdges; /* 圖中當前頂點數和邊數 */
} GraphAdjList;


void CreateALGraph(GraphAdjList *Gp)
{
    int i, j, k;
    EdgeNode *pe;
    cout << “輸入頂點數和邊數(空格分隔):” << endl;
    cin >> Gp->numNodes >> Gp->numEdges;

    for (i = 0 ; i < Gp->numNodes; i++)
    {
        cout << “輸入頂點信息:” << endl;
        cin >> Gp->adjList[i].data;
        Gp->adjList[i].firstedge = NULL;/* 將邊表置爲空表 */
    }

    for (k = 0; k <  Gp->numEdges; k++)/* 建立邊表 */
    {
        cout << “輸入邊(vi,vj)的頂點序號i,j(空格分隔):” << endl;
        cin >> i >> j;
        pe = (EdgeNode *)malloc(sizeof(EdgeNode));
        pe->adjvex = j;/* 鄰接序號爲j */
        /* 將pe的指針指向當前頂點上指向的結點 */
        pe->next = Gp->adjList[i].firstedge;
        Gp->adjList[i].firstedge = pe;/* 將當前頂點的指針指向pe */

        pe = (EdgeNode *)malloc(sizeof(EdgeNode));
        pe->adjvex = i;
        pe->next = Gp->adjList[j].firstedge;
        Gp->adjList[j].firstedge = pe;

    }
}

int main(void)
{
    GraphAdjList GL;
    CreateALGraph(&GL);

    return 0;
}

這裏的鄰接點插入使用了單鏈表創建中的頭插法,對於無向圖來說,一條邊對應都是兩個頂點,所以在循環中,一次就針對i和j分別進行了插入。



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