1. 程式人生 > >資料結構之圖的陣列表示法

資料結構之圖的陣列表示法

        圖( Graph )是 由頂點的有窮非空集合和頂點之間邊的集合組成,通常表示示為: G (V, E ) ,其中, G表示一個圖, V 是圖 G 中頂點的集合, E 是 圖 G 中邊的集合 。

       圖狀結構是一種比樹形結構更復雜的非線性結構。在樹狀結構中,結點間具有分支層次關係,每一層上的結點只能和上一層中的至多一個結點相關,但可能和下一層的多個結點相關.

                                   

        上面是圖的概念,看不懂是吧,其實我也看不懂,呵呵。其實這個圖的相關概念也沒有那麼玄乎,建議找找離散數學的書看看,如果沒有相關的基礎是很難理解圖這個坑爹的玩意的,光一堆術語就能把人搞的暈頭轉向的,更別說程式碼中指標還指來指去的(如果實在沒時間可以看看這個

連結)。

     資料結構中圖的基本操作如下:

(1) CreatGraph(G)輸入圖G 的頂點和邊,建立圖G 的儲存。
(2)DestroyGraph(G)釋放圖G 佔用的儲存空間。
(3)GetVex(G,v)在圖G 中找到頂點v,並返回頂點v 的相關資訊。
(4)PutVex(G,v,value)在圖G 中找到頂點v,並將value 值賦給頂點v。
(5)InsertVex(G,v)在圖G 中增添新頂點v。
(6)DeleteVex(G,v)在圖G 中,刪除頂點v 以及所有和頂點v 相關聯的邊或弧。
(7)InsertArc(G,v,w)在圖G 中增添一條從頂點v 到頂點w 的邊或弧。
(8)DeleteArc(G,v,w)在圖G 中刪除一條從頂點v 到頂點w 的邊或弧。
(9)DFSTraverse(G,v)在圖G 中,從頂點v 出發深度優先遍歷圖G。
(10)BFSTtaverse(G,v)在圖G 中,從頂點v 出發廣度優先遍歷圖G。
在一個圖中,頂點是沒有先後次序的,但當採用某一種確定的儲存方式儲存後,儲存結構中頂點的儲存次序構成了頂點之間的相對次序,這裡用頂點在
圖中的位置表示該頂點的儲存順序;同樣的道理,對一個頂點的所有鄰接點,採用該頂點的第i 個鄰接點表示與該頂點相鄰接的某個頂點的儲存順序,
在這種意義下,圖的基本操作還有:
(11)LocateVex(G,u)在圖G 中找到頂點u,返回該頂點在圖中位置。
(12)FirstAdjVex(G,v)在圖G 中,返回v 的第一個鄰接點。若頂點在G 中沒有鄰接頂點,則返回“空”。
(13)NextAdjVex(G,v,w)在圖G 中,返回v 的(相對於w 的)下一個鄰接頂點。若w 是v 的最後一個鄰接點,則返回“空”。


          圖的儲存結構有多種:陣列表示法,鄰接表,十字連結串列法,多重連結串列法,為了熟悉圖的運用我把每種表示方法都實現了一遍,有興趣的可以看看我後面更新的文章。當然這篇文章主要介紹陣列表示法,下面介紹陣列表示法。

        首先表示圖要就要表示圖中頂點的資訊又要表示頂點間的關係,考慮到圖是由頂點和邊或弧兩部分組成。合在一起比較困難,那就很自然地考慮到分兩個結構來分別儲存。頂點不分大小、主次,所以用一個一維陣列來儲存是很不錯的選擇。而邊或弧由於是頂點與頂點之間的關係, 一維搞不定,那就考慮用 一個二維陣列來儲存。於是我們的鄰接矩陣的方案就誕生了。圖的鄰接矩陣 ( Adjacency Matrix) 儲存方式是用兩個陣列來表示圈。一個一維陣列儲存圈中頂點資訊 ,一個二維陣列〈稱為鄰接矩陣)儲存圖中的邊或弧的資訊。

設圖G有n個頂點,則鄰接頂點是一個n * n的矩陣,具體定義如下(下面的是不帶權值的):

                           

比較抽象,那麼看兩個例子:

                                                       

看完不帶權的再看帶權的:

                                       

                              

大概看明白了,那麼我們來看陣列表示法的資料儲存結構:

#define INFINITY 65535 //表示無窮大-->在帶權的圖中用到,即網
#define MAX_VERTEX_NUM 20 //圖的最大定點數

#define MAX_INFO 20  //每條弧附帶資訊最大長度


//頂點關係型別
typedef int VRType;

//附加資訊型別
typedef char InfoType;

//頂點資料型別
typedef int VertexType;

//圖的種類:分別代表有向圖,有向網,無向圖,無向網
typedef enum {DG,DN,UDG,UDN} GraphKind;


typedef struct {
	VRType adj; //定點關係型別,對無權圖用1或0表示是否相鄰;對帶權圖,則為權值型別
	InfoType *info;	//附加資訊指標
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];


typedef struct {
	//頂點向量
	VertexType vexs[MAX_VERTEX_NUM];
	//鄰接矩陣
	AdjMatrix arcs;
	//圖的當前頂點數
	int vexnum;
	//圖的弧數
	int arcnum;
	//圖的種類
	GraphKind kind;
}MGraph;

上程式原始碼:

標頭檔案mgraph.h

/*---------------------------------------------------------------------------------
	* file:mgraph.h
	* date:10-9-2014
	* author:[email protected]
	* version:1.0
	* description:圖的陣列表示及基本操作
------------------------------------------------------------------------------------*/


#define TRUE 1
#define ERROR 0
#define OK 1
#define FALSE 0

#define INFINITY 65535 //表示無窮大-->在帶權的圖中用到,即網
#define MAX_VERTEX_NUM 20 //圖的最大定點數

#define MAX_INFO 20  //每條弧附帶資訊最大長度

typedef int Status;

//頂點關係型別
typedef int VRType;

//附加資訊型別
typedef char InfoType;

//頂點資料型別
typedef int VertexType;

//圖的種類:分別代表有向圖,有向網,無向圖,無向網
typedef enum {DG,DN,UDG,UDN} GraphKind;


typedef struct {
	VRType adj; //定點關係型別,對無權圖用1或0表示是否相鄰;對帶權圖,則為權值型別
	InfoType *info;	//附加資訊指標
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];


typedef struct {
	//頂點向量
	VertexType vexs[MAX_VERTEX_NUM];
	//鄰接矩陣
	AdjMatrix arcs;
	//圖的當前頂點數
	int vexnum;
	//圖的弧數
	int arcnum;
	//圖的種類
	GraphKind kind;
}MGraph;


//陣列標記某元素是否被訪問過
int visited[MAX_VERTEX_NUM];

//建立圖,包括有無向圖,有無向網
Status CreateGraph(MGraph *G);

//建立無向圖
Status CreateUDG(MGraph *G);

//建立有向圖
Status CreateDG(MGraph *G);

//建立無向網
Status CreateUDN(MGraph *G);

//建立有向網
Status CreateDN(MGraph *G);

//返回某頂點在圖中的位置
int LocateVex(MGraph G,VertexType v);

//列印元素
Status PrintElem(VertexType elem);

//深度優先遍歷圖
Status DFSTraverse(MGraph G,Status (*Visit) (VertexType));

//深度優先遞迴遍歷
void DFS(MGraph G,int i,Status (*Visit) (VertexType));

//返回v的值
VertexType GetVex(MGraph G,int v);

//對v進行賦值
Status PutVex(MGraph *G,int v,VertexType value);

//返回v的第一個鄰接頂點
int FirstAdjVex(MGraph G,int v);

//w是v的鄰接點,返回v相對於w的下一個鄰接點
int NextAdjVex(MGraph G,int v,int w);

//插入一個頂點,但是不進行插入弧
Status InsertVex(MGraph *G,VertexType v);

//刪除一個頂點和相關的弧
Status DeleVex(MGraph *G,VertexType v);

//在頂點v,w間插入一段弧或邊
Status InsertArc(MGraph *G,VertexType v,VertexType w);

//刪除一段弧或邊,但是不刪除頂點
Status DeleArc(MGraph *G,VertexType v,VertexType w);

實現具體檔案MGraph.c

/*---------------------------------------------------------------------------------
	* file:MGraph.c
	* date:10-9-2014
	* author:[email protected]
	* version:1.0
	* description:圖的陣列表示及基本操作
------------------------------------------------------------------------------------*/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mgraph.h"
#include "linkqueue.h"



/*
* @description:建立圖,包括有向圖,無向圖,有向網,無向網
*/
Status CreateGraph(MGraph *G) {
	printf("please enter the kind of the graph(DG:0,DN:1,UDG:2,UDN:3):");
	scanf("%d",&(*G).kind);

	switch((*G).kind) {
		case UDG:
			return CreateUDG(G);
			break;
		case DG:
			return CreateDG(G);
		case UDN:
			return CreateUDN(G);
			break;
		case DN:
			return CreateDN(G);
			break;
		default:
			return ERROR;
	}
}	



/*
* @description:建立無向圖
* @more:分幾步來做
	1.確定頂點數/弧數
	2.確定各個頂點的值
	3.初始化鄰接矩陣
	4.確定鄰接矩陣
*/
Status CreateUDG(MGraph *G) {
	int i,j,k,infoflag,len;
	char c;
	//設定一個暫存區和一個臨時指標
	char str[MAX_INFO];
	char *info;

	VertexType v1,v2;

	len = 0;

	//確定頂點數/弧數
	printf("please enter vexnum, arcnum is info(1 or 0):");
	scanf("%d,%d,%d",&(*G).vexnum,&(*G).arcnum,&infoflag);

	//確定各個頂點的值
	printf("the value of each vertex:");
	for(i = 0;i < (*G).vexnum ; i++)
		scanf("%d,",&(*G).vexs[i]);
	
	//初始化鄰接矩陣
	for(i = 0; i < (*G).vexnum; i++) 
		for(j = 0;j < (*G).vexnum ; j++) {
			(*G).arcs[i][j].adj = 0;	//無向圖
			(*G).arcs[i][j].info = NULL;
		}


	//確定鄰接矩陣
	printf("please %d heads and %d tails:\n",(*G).vexnum,(*G).arcnum);
	for(k = 0; k < (*G).arcnum; k++) {
		scanf("%d,%d",&v1,&v2);
		
		i = LocateVex(*G,v1);
		j = LocateVex(*G,v2);

		if(i >= 0 && j >= 0)
			(*G).arcs[i][j].adj = (*G).arcs[j][i].adj = 1;	//無向圖,對稱矩陣
		//如果頂點有附帶資訊,則輸入並申請空間
		if(infoflag) {
			printf("please enter the info:");
			while( (c = getchar()) != '#')
				str[len++] = c;

			info = (char *) malloc(len * sizeof(char));
			str[len] = '\0';

			strcpy(info,str);

			(*G).arcs[i][j].info = (*G).arcs[j][i].info = info;
		}
	}

	(*G).kind = UDG;

	return OK;
}





/*
* @description:建立有向圖
* @more:分幾步來做
	1.確定頂點數/弧數
	2.確定各個頂點的值
	3.初始化鄰接矩陣
	4.確定鄰接矩陣
*/
Status CreateDG(MGraph *G) {
	int i,j,k,len,infoflag;
	VertexType v1,v2;

	char str[MAX_INFO];
	char *info;
	char c;

	//確定頂點數/弧數
	printf("please enter vexnum , arcnum and is info(1 or 0):");
	scanf("%d,%d,%d",&(*G).vexnum,&(*G).arcnum,&infoflag);

	//確定各個頂點的值
	printf("the value of each vertex:");
	for(i = 0;i < (*G).vexnum ; i++)
		scanf("%d,",&(*G).vexs[i]);
	
	//初始化鄰接矩陣
	for(i = 0; i < (*G).vexnum; i++) 
		for(j = 0;j < (*G).vexnum ; j++) {
			(*G).arcs[i][j].adj = 0;	//有向圖
			(*G).arcs[i][j].info = NULL;
		}


	//確定鄰接矩陣
	printf("please %d heads and %d tails:\n",(*G).vexnum,(*G).arcnum);
	for(k = 0; k < (*G).arcnum; k++) {
		scanf("%d,%d",&v1,&v2);
		
		i = LocateVex(*G,v1);
		j = LocateVex(*G,v2);

		if(i >= 0 && j >= 0)
			(*G).arcs[i][j].adj = 1;	//有向圖

		//如果頂點有附帶資訊,則輸入並申請空間
		if(infoflag) {
			printf("please enter the info:");
			while( (c = getchar()) != '#')
				str[len++] = c;

			info = (char *) malloc(len * sizeof(char));
			strcpy(info,str);

			(*G).arcs[i][j].info = info;
		}
	}

	(*G).kind = DG;

	return OK;
}




/*
* @description:建立有向網
*/

Status CreateDN(MGraph *G) {
	int i,j,k,len,infoflag,w;
	VertexType v1,v2;

	char str[MAX_INFO];
	char *info;
	char c;

	//確定頂點數/弧數
	printf("please enter vexnum , arcnum and is info(1 or 0):");
	scanf("%d,%d,%d",&(*G).vexnum,&(*G).arcnum,&infoflag);

	//確定各個頂點的值
	printf("the value of each vertex:");
	for(i = 0;i < (*G).vexnum ; i++)
		scanf("%d,",&(*G).vexs[i]);
	
	//初始化鄰接矩陣
	for(i = 0; i < (*G).vexnum; i++) 
		for(j = 0;j < (*G).vexnum ; j++) {
			(*G).arcs[i][j].adj = INFINITY;	//有向網
			(*G).arcs[i][j].info = NULL;
		}


	//確定鄰接矩陣
	printf("please %d heads and %d tails and weights:\n",(*G).vexnum,(*G).arcnum);
	for(k = 0; k < (*G).arcnum; k++) {
		scanf("%d,%d,%d",&v1,&v2,&w);
		
		i = LocateVex(*G,v1);
		j = LocateVex(*G,v2);

		if(i >= 0 && j >= 0)
			(*G).arcs[i][j].adj = w;	//有向圖

		//如果頂點有附帶資訊,則輸入並申請空間
		if(infoflag) {
			printf("please enter the info:");
			while( (c = getchar()) != '#')
				str[len++] = c;

			info = (char *) malloc(len * sizeof(char));
			strcpy(info,str);

			(*G).arcs[i][j].info = info;
		}
	}

	(*G).kind = DN;

	return OK;
}






/*
* @description:建立無向網
*/

Status CreateUDN(MGraph *G) {
	int i,j,k,len,infoflag,w;
	VertexType v1,v2;

	char str[MAX_INFO];
	char *info;
	char c;

	//確定頂點數/弧數
	printf("please enter vexnum , arcnum and is info(1 or 0):");
	scanf("%d,%d,%d",&(*G).vexnum,&(*G).arcnum,&infoflag);

	//確定各個頂點的值
	printf("the value of each vertex:");
	for(i = 0;i < (*G).vexnum ; i++)
		scanf("%d,",&(*G).vexs[i]);
	
	//初始化鄰接矩陣
	for(i = 0; i < (*G).vexnum; i++) 
		for(j = 0;j < (*G).vexnum ; j++) {
			(*G).arcs[i][j].adj = INFINITY;	//無向網
			(*G).arcs[i][j].info = NULL;
		}


	//確定鄰接矩陣
	printf("please heads,tails and weights:\n");
	for(k = 0; k < (*G).arcnum; k++) {
		scanf("%d,%d,%d",&v1,&v2,&w);
		
		i = LocateVex(*G,v1);
		j = LocateVex(*G,v2);

		if(i >= 0 && j >= 0)
			(*G).arcs[i][j].adj = (*G).arcs[j][i].adj = w;	//無向網

		//如果頂點有附帶資訊,則輸入並申請空間
		if(infoflag) {
			printf("please enter the info:");
			while( (c = getchar()) != '#')
				str[len++] = c;

			info = (char *) malloc(len * sizeof(char));
			strcpy(info,str);

			(*G).arcs[i][j].info = info;
		}
	}

	(*G).kind = UDN;

	return OK;
}







/*
* @description:判斷圖中是否存在v頂點,存在則返回該頂點在圖中的位置,否則返回其他資訊
*/
int LocateVex(MGraph G,VertexType v) {
	int i;

	for(i = 0;i < G.vexnum; i++)
		//匹配則返回
		if(G.vexs[i] == v)
			return i;

	return -1;
}


/*
* @description:深度優先遍歷圖
* @more:分為兩步
	1.一定要重新初始化訪問記錄陣列
	2.訪問沒有訪問過的頂點,並更新訪問記錄陣列
* @本函式中的第二個迴圈主要是為了保證每個頂點都能被訪問到
   而DFS中的迴圈是在尋找當前節點的相鄰節點來訪問
   關鍵的關鍵在於遞迴的理解-->廢話
*/
Status DFSTraverse(MGraph G,Status (*Visit) (VertexType)) {
	int i;
	//初始化訪問記錄陣列
	for(i = 0;i < G.vexnum; i++)
		visited[i] = FALSE;
	
	for(i = 0;i < G.vexnum ; i++) 
		if(!visited[i])
			DFS(G,i,Visit);

	return OK;
}



/*
* @description:深度優先遞迴遍歷
*/
void DFS(MGraph G,int i,Status (*Visit) (VertexType)) {
	int j,w;

	//標記
	visited[i] = TRUE;
	Visit(G.vexs[i]);

	for(w = FirstAdjVex(G,i); w >= 0; w = NextAdjVex(G,i,w))
		if(!visited[w])
			DFS(G,w,Visit);
}



/*
* @description:圖的廣度優先遍歷
* @more:值得注意的是廣度遍歷和樹中的層序遍歷採用的是同樣的思路-->採用佇列輔助
*/
Status BFSTraverse(MGraph G,Status (*Visit)(VertexType)) {
	LinkQueue Q;
	int i,w,u;
	
	//必須重新初始化訪問標記陣列
	for(i = 0;i < G.vexnum; i++) 
		visited[i] = FALSE;

	InitQueue(&Q);

	//用於確保每個頂點都會被訪問到
	for(i = 0;i < G.vexnum; i++) {
		if(!visited[i]) {
			Visit(G.vexs[i]);
			visited[i] = TRUE;

			//進隊
			EnQueue(&Q,i);

			while(!QueueEmpty(Q)) {
				//出隊一個元素
				DeQueue(&Q,&u);
				for(w = FirstAdjVex(G,u); w >= 0; w = NextAdjVex(G,u,w)) {
					if(!visited[w]) {
						visited[w] = TRUE;
						Visit(G.vexs[w]);
						EnQueue(&Q,w);
					}
				}
			}
		}
	}

	return OK;
}





/*
* @description:返回v的值
*/
VertexType GetVex(MGraph G,int v) {
	if(v >= G.vexnum || v < 0)
		exit(ERROR);

	return G.vexs[v];
}



/*
* @description:對v進行賦值
*/
Status PutVex(MGraph *G,int v,VertexType value) {
	if(v >= (*G).vexnum || v < 0)
		exit(ERROR);

	(*G).vexs[v] = value;

	return OK;
}

/*
* @description:返回v(序號)的第一個相鄰節點(序號)
*/
int FirstAdjVex(MGraph G,int v) {
	if(v > G.vexnum || v < 0)
		return -1;
	
	int i,j;

	j = 0;

	//如果是網
	if(G.kind == DN || G.kind == UDN )
		j = INFINITY;

	for(i = 0;i < G.vexnum; i++) 
		if(G.arcs[v][i].adj != j)
			return  i;

	return -1;
}

/*
* @description:w是v的相鄰節點,返回v相對w的下一個節點的序號,否則返回-1
*/
int NextAdjVex(MGraph G,int v,int w) {
	int i,j;
	
	j = 0;
	//如果為網
	if(G.kind == DN || G.kind == UDN)
		j = INFINITY;
	//兩頂點不相鄰
	if(G.arcs[v][w].adj == j)
		return -1;
	//從w之後的節點開始就可以
	for(i = w + 1; i < G.vexnum; i++) 
		if(G.arcs[v][i].adj != j)
			return i;

	return -1;
}


/*
* description:插入一個頂點,但是進行弧的插入,交給後面的插入弧操作進行
* @more:注意需要同時對鄰接矩陣行和列的跟新資訊,還有這裡的插入是直接在
	的位置進行插入,不指定位置
*/
Status InsertVex(MGraph *G,VertexType v) {
	int i;

	//進行賦值
	(*G).vexs[(*G).vexnum] = v;

	if((*G).kind == DN || (*G).kind == UDN)
		for(i = 0; i <= (*G).vexnum; i++) {
			//對行的鄰接關係進行初始化
			(*G).arcs[(*G).vexnum][i].adj = INFINITY;
			//對列的鄰接關係進行初始化
			(*G).arcs[i][(*G).vexnum].adj = INFINITY;

		}

	else 
		for(i = 0; i <= (*G).vexnum; i++) {
			//對行的鄰接關係進行初始化
			(*G).arcs[(*G).vexnum][i].adj = 0;
			//對列的鄰接關係進行初始化
			(*G).arcs[i][(*G).vexnum].adj = 0;

		}
	
	//對行進行初始化
	(*G).arcs[(*G).vexnum][i].info = NULL;
	//對列進行初始化
	(*G).arcs[i][(*G).vexnum].info = NULL;

	//圖的頂點數目加一
	(*G).vexnum++;

	return OK;
}




/*
* @description:刪除G中的頂點v其相關的弧(難點在於弧的刪除)
*/
Status DeleVex(MGraph *G,VertexType v) {
	int k,i,j;
	VRType m;

	m = 0;
	k = LocateVex(*G,v);

	if(k >= (*G).vexnum || k < 0)
		return ERROR;

	//圖的型別為網
	if((*G).kind == DN || (*G).kind == UDN)
		m = INFINITY;
	/*
	這裡主要是釋放弧的附帶資訊,如果是有向圖則為釋放入弧,
	如果是無向圖,由於其是對稱矩陣,釋放列或行就可
	*/
	for(i =0;i < (*G).vexnum; i++)
		if((*G).arcs[i][k].adj != m) {
			if((*G).arcs[i][k].info)
				free((*G).arcs[i][k].info);
			(*G).arcnum--;
		}

	//有向圖存在出弧
	if((*G).kind == DG || (*G).kind == DN) 
		for(i = 0;i < (*G).vexnum; i++)
			if((*G).arcs[k][i].adj != m) {
				if((*G).arcs[k][i].info)
					free((*G).arcs[k][i].info);

				(*G).arcnum--;
			}
	
	//將頂點陣列中的v之後的元素前移
	for(i = k + 1; i < (*G).vexnum; i++) 
		(*G).vexs[i-1] = (*G).vexs[i];
	
	//鄰接矩陣v之後的前移動
	for(i = 0;i < (*G).vexnum; i++)
		for(j = k + 1; j < (*G).vexnum ; j++)
			(*G).arcs[i][j-1] = (*G).arcs[i][j];

	//鄰接矩陣v之下的上移
	for(i = 0;i < (*G).vexnum; i++) 
		for(j = k +1; j < (*G).vexnum ; j++)
			(*G).arcs[j-1][i] = (*G).arcs[j][i];

	(*G).vexnum--;


	return OK;
}


/*
* @description:增添弧<v,w>,若是無向的,則還增添對稱弧<w,v>
		注意v,w已經存在圖中
*/
Status InsertArc(MGraph *G,VertexType v,VertexType w) {
	int v1,w1,infoflag,len;
	char str[MAX_INFO],c,*info;

	//獲取頂點對應位置
	v1 = LocateVex(*G,v);
	w1 = LocateVex(*G,w);
	len = 0;
	
	if(v1 < 0 || w1 < 0)
		return ERROR;
	
	
	if((*G).kind == DN || (*G).kind == UDN) {
		printf("please enter the weight:");
		scanf("%d",&(*G).arcs[v1][w1].adj);
	}
	else 
		(*G).arcs[v1][w1].adj = 1;

	printf("please make sure is info(1 or 0):");
	scanf("%d",&infoflag);

	//邊或弧有附帶資訊
	if(infoflag) {
		while( (c = getchar()) != '#') 
			str[len++] = c;

		info = (char *) malloc(len * sizeof(char));
		strcpy(info,str);
		(*G).arcs[v1][w1].info = info;
	}
	
	//注意如果是無向的,應該新增對稱邊<w,v)
	if((*G).kind == UDG || (*G).kind == UDN) {
		(*G).arcs[w1][v1].adj = (*G).arcs[v1][w1].adj;
		(*G).arcs[w1][v1].info = (*G).arcs[v1][w1].info;
	}

	(*G).arcnum++;

	return OK;
}


/*
* @description:刪除弧或邊<v,w>,如果圖為無向,則同時刪除其對稱弧或邊
*/
Status DeleArc(MGraph *G,VertexType v,VertexType w) {
	int v1,w1,m;

	v1 = LocateVex(*G,v);
	w1 = LocateVex(*G,w);
	m = 0;
	
	if(v1 < 0 || w1 <0)
		return ERROR;
	
	if((*G).kind == DN || (*G).kind == UDN)
		m = INFINITY;


	(*G).arcs[v1][w1].adj = m;

	if((*G).kind == UDN || (*G).kind == UDG)
		(*G).arcs[w1][v1].adj = (*G).arcs[v1][w1].adj;

	if((*G).arcs[v1][w1].info) {
		free((*G).arcs[v1][w1].info);

		if((*G).kind == UDN || (*G).kind == UDG)
			free((*G).arcs[w1][v1].info);
	}
	(*G).arcnum--;

	return OK;
}


/*
* @description:列印元素
*/
Status PrintElem(VertexType elem) {
	printf("%d",elem);
	return OK;
}

測試檔案:test.c

/*---------------------------------------------------------------------------------
	* file:MGraph.c
	* date:10-9-2014
	* author:[email protected]
	* version:1.0
	* description:圖的陣列表示及基本操作
------------------------------------------------------------------------------------*/


#include <stdio.h>
#include "mgraph.h"


int main(int argc,char *argv[]) {
	MGraph G;
	//建圖
	CreateGraph(&G);

	//深度優先遍歷圖
	DFSTraverse(G,PrintElem);
	printf("\n");
	BFSTraverse(G,PrintElem);
	printf("\n");
         /*
    測試用例結果:
    please enter the kind of the graph(DG:0,DN:1,UDG:2,UDN:3):2
    please enter vexnum, arcnum is info(1 or 0):8,8,0
    the value of each vertex:1,2,3,4,5,6,7,8
    please 8 heads and 8 tails:
    1,2
    1,3
    2,4
    2,5
    3,6
    3,7
    4,8 
    5,8
    12485367
    12345678

    */

 }

完整的原始碼可以看:GitHub

 本部落格持續更新,歡迎指正,互相學習。

相關推薦

資料結構陣列表示

        圖( Graph )是 由頂點的有窮非空集合和頂點之間邊的集合組成,通常表示示為: G (V, E ) ,其中, G表示一個圖, V 是圖 G 中頂點的集合, E 是 圖 G 中邊的集合 。        圖狀結構是一種比樹形結構更復雜的非線性結構。在樹

資料結構】鄰接矩陣表示的深度廣度優先遍歷遞迴和非遞迴遍歷

假設有以下結構的圖: 用鄰接矩陣表示如下: 因為他是無向圖,我們可以發現他的矩陣是對角對稱的。矩陣中每一行每一列都可以看成是一個頂點,矩陣中的元素表示著該頂點與其他頂點的關係,當元素的值為1說明它與對應列的頂點有邊相連,如果他們的值為0,表示他們沒有邊相

資料結構的關鍵路徑

title: 資料結構之圖的關鍵路徑 tags: 資料結構與演算法之美 一、AOE和AOV網 1.AOE網 AOE-網:指用邊表示活動的網,是一個帶權的有向無環圖,其中,頂點表示事件弧表示活動,權表示活動持續的時間,通常一個AOE-網可用來估算工程的完成時間。 2.AOV網 指用頂點表示活動

資料結構(帶權 迪傑斯特拉演算法)

// 主要思想是: 每次尋找最小的邊  這樣的話從上一個節點 到這個節點的值 是最小的 當找到最小的邊時,把final[v] = true 表示從原點到這個節點的最小值 已經找到了   <!DOCTYPE html> <html> &l

資料結構(鄰接表 稀疏

<!DOCTYPE html> <html> <head>     <title>鄰接表</title>     <meta charset="utf-8">

資料結構的最小生成樹

我們把構造連通網的最小代價生成樹稱為最小生成樹,找連通網的最小生成樹,經典的有兩種演算法:普里姆演算法(Prim)和克魯斯卡爾演算法(Kruskal)。 普里姆演算法 有如下鄰接矩陣,9個頂點,左側數字為行號,INFINITY為極大值65535,MAXVEX為頂點個數最大值,此處

資料結構的遍歷

圖的遍歷是和樹的遍歷類似,我們希望從圖中某一點出發訪問圖中其餘頂點,且使每一個頂點僅被訪問一次,這一過程就叫做圖的遍歷。 深度優先遍歷 深度優先遍歷,也稱之為深度優先搜尋,簡稱DFS。首先指定一個規則,在沒有碰到重複頂點的情況下,始終向右手邊走,A-B-C-D-E-F,走到F時發

資料結構篇(2):的基本操作 深度和廣度遍歷

程式碼實現 main.cpp(主函式) #include <iostream> #include "CMap.h" using namespace std; /** 圖的的儲存:鄰接矩陣 圖的遍歷:深度+廣度 A / \

資料結構篇(1):概述

圖的概念 1.有向圖(由節點和方向箭頭構成)無向圖(只有節點,相當於每條連線都是雙向的) 2.出度:頂點的箭頭指出;入度:頂點的箭頭指入; 3.有向圖:弧;無向圖:邊; 5.權值:弧或者邊上的資料 圖的儲存結構 陣列儲存 1.鄰接矩陣(頂點陣列【索引+資料】+鄰接矩

資料結構學習筆記

一、圖的定義:     圖(Graph)是由頂點的有窮非空集合和頂點之間邊的集合組成,通常表示為:G(V,E),其中,G表示一個圖,V表示圖G中頂點的集合,E是圖G中的邊集合。     a.線性表中的資料元素我們稱為元素,樹中資料元素稱為節點,而圖中的

資料結構鄰接表

還是插入一段程式碼來解釋鄰接表的建立過程。 //自己建立一個鄰接表 //邊表結點 typedef struct { int adjvex;//該邊的頭結點 int weight;//權值 EdgeNode *next;//該邊尾結點的下一條邊 }EdgeNo

資料結構深度搜索八皇后

//八皇后問題 #include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> using namespace std; int a[100],coun

資料結構JAVA陣列重寫

package com.ws.scala; public class Array { private E[] data; private int size; //實際有值長度 /** * 預設構造 * 預設陣列容量指定為10 */ public Arra

資料結構樹的雙親表示

#include<iostream> #include<malloc.h> #include<stdlib.h> using namespace std; #define max 100 typedef char TElemType;

資料結構

1.圖的定義 圖(graph)是由一些點(vertex)和這些點之間的連線(edge)所組成的;其中,點通常稱為頂點(vertex),而點到點之間的連線通常稱之為邊或者弧(edge)。通常記為G=(V,E)。 2.圖的分類 圖通常分為有向圖和無向圖,而其表示表示方式

資料結構(的基本操作)

由於圖的基本操作的程式碼較多,我放到這一章來寫。圖可以用兩種方法來儲存,但是本人偏愛連結串列的表示方法,所以以下程式碼也都是是基於鄰接連結串列的儲存方式。 1 /* 2 以下儲存結構參考嚴蔚敏版資料結構,不懂的可以翻閱檢視 3 */ 4 const int UNDIGR

資料結構的簡介)

圖的定義:   一個圖G = (V,E)由頂點(vertex)集 V 合邊(edge)集 E 組成。每條邊(v,w)就是一個點對,其中v,w ∈ V。有時也把邊稱作弧。如果點對是有序的,那麼圖就叫做有向圖。頂點 v 和 w 領接邊 (v,w) ∈ E。在一個具有邊(

C語言資料結構——樹的雙親表示

1、樹的雙親表示法: 2、/* bo6-4.c 樹的雙親表儲存(儲存結構由c6-4.h定義)的基本操作(14個) */ Status InitTree(PTree *T) { /* 操作結果: 構造空樹T */ (*T).n=0; r

資料結構的深度優先遍歷和廣度優先遍歷

1.圖的簡單介紹 上圖就是一個圖(無線圖),由頂點和連線組成 圖可以分為無向圖和有向圖(這個又有出度、入度的概念)、網,一般來說圖有兩種常用的表示方式,鄰接矩陣(用二維陣列的形式表示)和鄰接表(主要是陣列+連結串列的形式表示),圖常用的遍歷方式有深度優先遍歷(DFS)和廣

資料結構的鄰接矩陣儲存方法

這段時間遇到了關於圖的問題,然後發現之前學過的內容都還給老師了,因此又看了一遍,做個彙總。 圖的定義: 圖G是由頂點的非空有限集合V與邊的集合E構成的,形式化定義如下: G = (V,E) 圖可以分為有向圖和無向圖。無向圖是指圖的每一條邊都沒有方向;有向圖是指圖的每一條邊都