图的存储不外乎一个记录图中顶点的数组,一个表示弧的结构.十字链表的表示如下:
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