1. 程式人生 > >圖的十字連結串列儲存結構

圖的十字連結串列儲存結構

圖的儲存不外乎一個記錄圖中頂點的陣列,一個表示弧的結構.十字連結串列的表示如下:

typedef char Graph_style;
typedef struct Graph_node{  //弧結點
	int itail;   //該弧的尾頂點所在頂點陣列中的位置
	struct Graph_node *itail_point;   //指向下一個以itail為尾的弧
	int ihead;	//該弧的頭頂點所在頂點陣列中的位置
	struct Graph_node *ihead_point;		//指向下一個以Ihead為頭的弧
}Graph_node;
typedef struct Graph_head{  儲存圖中頂點的資料結構                            
	Graph_node *in_point;  //指向一個新的以該頂點為尾的弧..
	Graph_style data;
	Graph_node *out_point;	//指向一個新的以該頂點為頭的弧..
}Graph_head;
//圖的結構...
typedef struct Graph{
	int Graph_vertexcount;//圖的頂點個數
   	int Graph_arccount;   //圖的弧條數
	Graph_head *array_head;//指向存放的所有頂點,以及頂點中的資料結構
 	Graph_style *local_array;  //專門存放頂點的內部陣列...其中只有頂點.與 array_head中的頂點序列相同  專門用來確定弧頭弧尾的位置                   
}Graph;


在對圖進行操作的時候,還需要一個確定弧尾和弧頭在array_head中的位置函式...

int Local_Int(Graph &G, Graph_style head_date){ //尋找該頂點在 圖G頭結點陣列中的位置
	int count = 0;
	while(count < G.Graph_vertexcount){
		if(G.local_array[count] == head_date)
			return count;
		count++;
	}
	printf("未找到該頂點!\n");
}


十字連結串列中的核心程式碼.

	fscanf(fp, "%c%*c%*c%*c%c%*c", &tail, &head);
		itail = Local_Int(G, tail);
		jhead = Local_Int(G, head);
		arc_point = (Graph_node *) malloc(sizeof(Graph_node));
		arc_point->itail = itail;	//弧尾在頭頂點陣列中的位置
		arc_point->ihead = jhead;	//弧頭的位置
		arc_point->itail_point = G.array_head[itail].out_point;  //倒敘插入法..與新弧的尾頂點相同的後繼..始終是放在該弧的尾頂點的out指標域中的...
		arc_point->ihead_point = G.array_head[jhead].in_point;	 //倒敘插入法..與新弧的頭頂點相同的後繼..始終是放在該弧的頭頂點的in指標域中的...
		//給頭頂點的指標域賦值
		G.array_head[itail].out_point = arc_point;	//arc_point這條弧是從itail-->jhead的..所以它是從itail出去的..
		G.array_head[jhead].in_point  = arc_point;	//進入到jhead所在的頂點..
			//在以後的倒插過程中..新弧的各個方向的後繼..只需在其各個頂點中的指標域中尋找即可完成..無需刻意的到弧中去需找

從程式碼上分析原理...首先讀取一條弧 tail-->head ,然後對這條弧的弧尾和弧頭的位置進行查詢.具體是itail = Local_Int(G, tail);          jhead = Local_Int(G, head);

然後對該弧分配一塊記憶體...從對弧的資料結構定義上我們知道:

typedef struct Graph_node{  //弧結點
	int itail;   //該弧的尾頂點所在頂點陣列中的位置
	struct Graph_node *itail_point;   //指向下一個以itail為尾的弧
	int ihead;	//該弧的頭頂點所在頂點陣列中的位置
	struct Graph_node *ihead_point;		//指向下一個以Ihead為頭的弧
}Graph_node;

它的 itail和ihead分別表示該弧在圖G頂點陣列array_head中的位置...itail_point 和 ihead_point 指標分別指向 與這條弧的弧尾相同的弧 和 與這條弧的弧頭相同的弧..即將圖中相同尾頂點的弧 itail--> X  連結起來....和 將頭頂點相同的弧X-->ihead  鏈 接起來..

頂點的資料結構中:

typedef struct Graph_head{  儲存圖中頂點的資料結構                            
	Graph_node *in_point;  //指向一個新的以該頂點為尾的弧..
	Graph_style data;
	Graph_node *out_point;	//指向一個新的以該頂點為頭的弧..
}Graph_head;

in_point 和out_point  分別指向 進入到data的(以data為頭的弧) 和 從data出去的(以data為尾的弧)...

由於在對弧進行操作的時候採用的 倒敘將弧逐步 連結成連結串列的...所以需要一個變數來儲存上一個關係弧的位置資訊. .這裡我們用頭結點中的in_point 和 out_point 來表示..

在對頭頂點的指標進行賦值的時候先初始化為NULL , 使得在第一次執行到:

arc_point->itail_point = G.array_head[itail].out_point; 

 arc_point->ihead_point = G.array_head[jhead].in_point; 

這兩條語句的時候 ..將該弧作為最後一條弧..並將指標域 賦為NULL..來表示結束...

而頭結點中的指標資訊 ..始終是指向剛剛那條弧的  G.array_head[itail].out_point = arc_point;     G.array_head[jhead].in_point  = arc_point;

由於是頭頂點中的指標是在對弧之後操作的..所以..頭頂點中就可以儲存 上一個弧的資訊了. ..

對於一條弧...tail-->head; 都有..這條弧是從tail發出的..即以tail為尾..從head進入...即以head 為頭...所以在相應的頭頂點資料機構中肯定可以賦值..而這個指標值.將恰好是 將來與此弧 tail 相同..或者 head相同 的弧資訊...新弧只需要利用在頭頂點中保持的資訊 即可完成 相應連結串列的建立...

=================================================================

===============================================================

十字連結串列 完整程式碼. .

===============================================================

/************************************************************************/
/*                    圖的十字連結串列儲存                                   */
/************************************************************************/
typedef char Graph_style;
typedef struct Graph_node{  //弧結點
	int itail;   //該弧的尾頂點所在頂點陣列中的位置
	struct Graph_node *itail_point;   //指向下一個以itail為尾的弧
	int ihead;	//該弧的頭頂點所在頂點陣列中的位置
	struct Graph_node *ihead_point;		//指向下一個以Ihead為頭的弧
}Graph_node;
typedef struct Graph_head{
	Graph_node *in_point;  //指向一個新的以該頂點為尾的弧..
	Graph_style data;
	Graph_node *out_point;	//指向一個新的以該頂點為頭的弧..
}Graph_head;
typedef struct Graph{
	int Graph_vertexcount;
	int Graph_arccount;
	Graph_head *array_head;
	Graph_style *local_array;
}Graph;

int Local_Int(Graph &G, Graph_style head_date){ //尋找該頂點在 圖G頭結點陣列中的位置
	int count = 0;
	while(count < G.Graph_vertexcount){
		if(G.local_array[count] == head_date)
			return count;
		count++;
	}
	printf("未找到該頂點!\n");
}

void Creat_Graph_Link_2(Graph &G){
	int ver, arc;
	Graph_style tail, head;
	int itail, jhead;
	FILE *fp = fopen("C://Users//Administrator//Desktop//圖//圖的十字連結串列.txt", "r");
	fscanf(fp, "%d %d%*c", &G.Graph_vertexcount, &G.Graph_arccount);
	fscanf(fp, "%*s%*c");
	G.local_array = (Graph_style *)malloc(G.Graph_vertexcount * sizeof(Graph_style));
	fscanf(fp, "%s%*c", G.local_array);
	fscanf(fp, "%*s%*c");
//	printf("G.Graph_vertexcount = %d, G.Graph_arccount = %d,G.local_array = %s", G.Graph_vertexcount, G.Graph_arccount, G.local_array);
	G.array_head = (Graph_head *) malloc(G.Graph_vertexcount * sizeof(Graph_head));
	for(ver = 0; ver < G.Graph_vertexcount; ver++){		//頭頂點 初始化...
		G.array_head[ver].data = G.local_array[ver];
		G.array_head[ver].in_point = NULL;
		G.array_head[ver].out_point = NULL;
	}
	
	for(arc = 0; arc < G.Graph_arccount; arc++){
		Graph_node *arc_point = NULL; //弧結點
		fscanf(fp, "%c%*c%*c%*c%c%*c", &tail, &head);
		itail = Local_Int(G, tail);
		jhead = Local_Int(G, head);
		arc_point = (Graph_node *) malloc(sizeof(Graph_node));
		arc_point->itail = itail;	//弧尾在頭頂點陣列中的位置
		arc_point->ihead = jhead;	//弧頭的位置
		arc_point->itail_point = G.array_head[itail].out_point;  //倒敘插入法..與新弧的尾頂點相同的後繼..始終是放在該弧的尾頂點的out指標域中的...
		arc_point->ihead_point = G.array_head[jhead].in_point;	 //倒敘插入法..與新弧的頭頂點相同的後繼..始終是放在該弧的頭頂點的in指標域中的...
		//給頭頂點的指標域賦值
		G.array_head[itail].out_point = arc_point;	//arc_point這條弧是從itail-->jhead的..所以它是從itail出去的..
		G.array_head[jhead].in_point  = arc_point;	//									 進入到jhead所在的頂點..
											//在以後的倒插過程中..新弧的各個方向的後繼..只需在其各個頂點中的指標域中尋找即可完成..無需刻意的到弧中去需找
	}
	fclose(fp);
}

void Show_Graph(Graph &G){   //列印頂點的各個方向的弧.
	int ver, arc;
	Graph_node *p;
	for(ver = 0; ver < G.Graph_vertexcount; ver++){
		p   = G.array_head[ver].out_point;	//先列印以頂點為尾的弧..
		printf("以%c為尾的弧: \n", G.array_head[ver].data);
		while(p){
			
			printf("%c-->%c\n", G.array_head[p->itail].data, G.array_head[p->ihead].data);
			p = p->itail_point;	 //讓p指向下一條以 該弧的尾頂點相同的弧...
		}
		p	= G.array_head[ver].in_point;
		printf("以%c為頭的弧: \n", G.array_head[ver].data);
		while(p){
			
			printf("%c-->%c\n", G.array_head[p->itail].data, G.array_head[p->ihead].data);
			p = p->ihead_point;
		}
	}

}

int main(){
	Graph G;
	Creat_Graph_Link_2(G);
	Show_Graph(G);

	return 0;
}


============================================================================================================================

我擦.. 手好生啊 .. 不知所云 啊.. . ...萬事開頭難啊. . .就這麼湊合下吧 .. .

2013年11月27日17:17:06