圖的存儲結構 --- 鄰接表


圖的鄰接矩陣存儲方式方便實現和操作,但是當遇到圖爲稀疏圖的時候這種鄰接矩陣的存儲將大部分的存儲空間都浪費掉了, 比如有5個頂點但是隻有一條弧的稀疏圖,他的存儲只有一條信息是有用的,如下鄰接矩陣的存儲:



這個時候只有map[1][0] = 9, 其餘的存儲空間都沒有被利用起來,這時候圖的另外一種存儲方式就顯示出了巨大的優勢,那就是圖的鄰接表存儲方式。


鄰接表是將一個一維數組和鏈表結合起來作爲圖的存儲方式, 一維數組存儲頂點信息, 頂點數組中每個元素都有一個指向第一個鄰接頂點的指針,頂點的所有鄰接頂點組成一個單鏈表。 如下所示爲無向圖的單鏈表存儲方式:




從存儲示意圖可以看出來, 鄰接表的每個頂點都有一個data域和一個指向第一個鄰接頂點(其實任何一個鄰接頂點都可以稱之爲第一個)域兩部分組成, data域負責存儲當前頂點的信息,而第一個鄰接頂點域則是該頂點鄰接表的第一個頭結點。每一個鄰接頂點域都包含一個自己頂點信息(自己在頂點數組中的下標)和一個next指針指向下一個鄰接頂點。有了這樣一個結構,我們想要知道兩個節點是否相通則可以遍歷對於頂點的鏈表看是否存在第二個節點即可,當然有向圖只需要遍歷起點頂點的鏈表,無向圖則不用區分這些。說道有向圖,我們要注意一點的是,有向圖的鄰接表存儲都是用弧尾到弧首的放心進行存儲,比如下面所示:



當然你也可以使用相反的方式存儲,從弧首到弧尾進行逆向存儲,我們稱這種方式爲逆鄰接表存儲方式,方法類似不在重複複述介紹,有興趣的可以在紙上畫畫,很容易就能弄出來。下面看代碼的具體實現:

typedef int EdgeType;
typedef int VertexType;
#define MAXVEERTEX 100

typedef struct edge			// 邊表結點
{
	int ver_index;			// 鄰接頂點域 說明鄰接頂點在數組中的下標
	edge* next;				// 下一個鄰接頂點域
}EdgeNode;


typedef struct vertex		// 頂點表結構
{
	VertexType ver_noee;	// 頂點信息
	EdgeNode* first_vertex;	// 頂點鏈表
}VertexNode, AdjList[MAXVEERTEX];

typedef struct graph
{
	AdjList list;
	int ver_num, edge_num;
}Graph;

void create_adjlist_graph(Graph* g)
{
	cout << "Input graph vertexs and edges :" << endl;
	cin >> g->ver_num >> g->edge_num;

	for (int i = 0; i < g->ver_num; i++)
	{
		cout << " Input graph vertex info" << endl;
		cin >> g->list[i].ver_noee;
		g->list[i].first_vertex = NULL;
	}

	
	int val;
	VertexType vi, vj;
	EdgeNode* node = NULL;

	for (int i = 0; i < g->edge_num; i++)
	{
		cout << "input vertex and edge info for example(vi vj x)" << endl;
		cin >> vi >> vj >> val;
		node = (EdgeNode*) malloc(sizeof(EdgeNode));
		if (node == NULL)  exit(0);

		node->ver_index = vj;
		node->next = g->list[vi].first_vertex;
		g->list[vi].first_vertex = node;

		node = (EdgeNode*) malloc(sizeof(EdgeNode));
		if (node == NULL)  exit(0);
		node->ver_index = vi;
		node->next = g->list[vj].first_vertex;
		g->list[vj].first_vertex = node;
	}
}




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