圖的十字連結串列儲存結構
圖的儲存不外乎一個記錄圖中頂點的陣列,一個表示弧的結構.十字連結串列的表示如下:
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