图->存储结构->十字链表

文字描述

  十字链表是有向图的另一种链式存储结构. 在十字链表中,对应于有向图中每一条弧有一个结点,对应于每个顶点也有一个结点.这些结点的结构如下所示:

 

  在弧结点中有5个域: 尾域tailvex和头域headvex分别指示弧尾和弧头这两个顶点在图中的位置,链域hlink指向与弧头相同的下一条弧, 而链域tlink指向弧尾相同的下一条弧, info域指向该弧的相关信息; 弧头相同的弧在同一链表上, 弧尾相同的弧也在同一链表上. 它们的头结点即为顶点结点,它由3个域组成:其中data域存储和顶点相关的信息,如顶点名称等; firstin和firstout为两个链域,分别指向以该顶点为弧头或弧尾的第一个弧结点.

示意图

算法分析

  建立十字链表的时间复杂度和建立邻接表是相同的. 而且在十字链表中既容易找到以vi为尾的弧,也容易找到以vi为头的弧,因而容易求得顶点的出度和入度.

代码实现

 

  1 /*
  2     以十字链表作为图的存储结构创建图。
  3 */
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 
  8 #define    MAX_VERTEX_NUM    20    //最大顶点数
  9 #define DEBUG
 10 typedef enum {DG, DN, UDG, UDN} GraphKind; //{有向图,有向网,无向图,无向网}
 11 typedef char InfoType;
 12 typedef char VertexType;
 13 //弧结点
 14 typedef struct ArcBox{
 15     int tailvex, headvex;//该弧的尾和头顶点的位置
 16     struct ArcBox *hlink, *tlink;//分别为弧头相同和弧尾相同的弧的链域
 17     InfoType *info;//该弧相关的信息
 18 }ArcBox;
 19 //顶点结点
 20 typedef struct VexNode{
 21     VertexType data;//顶点名称
 22     ArcBox *firstin, *firstout;//分别指向该顶点第一条入弧和出弧
 23 }VexNode;
 24 typedef struct{
 25     VexNode xlist[MAX_VERTEX_NUM];//表头向量
 26     int vexnum, arcnum;//有向图的当前顶点数和弧数
 27     GraphKind kind;//图类型
 28 }OLGraph;
 29 
 30 /*
 31     若G中存在顶点u,则返回该顶点在图中位置;否则返回-1。
 32 */
 33 int LocateVex(OLGraph G, VertexType v)
 34 {
 35     int i = 0;
 36     for(i=0; i<G.vexnum; i++){
 37         if(G.xlist[i].data == v)
 38             return i;
 39     }
 40     return -1;
 41 }
 42 
 43 /*
 44     若G中存在顶点位置loc存在,则返回其顶点名称
 45 */
 46 VertexType LocateVInfo(OLGraph G, int loc)
 47 {
 48     return G.xlist[loc].data;
 49 }
 50 
 51 /*
 52     采用十字链表的存储结构,构造有向图
 53  */
 54 int CreateDG(OLGraph *G)
 55 {
 56     int i = 0, j = 0, k = 0, IncInfo = 0;
 57     int v1 = 0, v2 = 0;
 58     char tmp[10] = {0};
 59     ArcBox *p = NULL;
 60 
 61     printf("输入顶点数,弧数,其他信息标志位: ");
 62     scanf("%d,%d,%d", &G->vexnum, &G->arcnum, &IncInfo);
 63 
 64     for(i=0; i<G->vexnum; i++){
 65         //输入顶点值
 66         printf("输入第%d个顶点: ", i+1);
 67         memset(tmp, 0, sizeof(tmp));
 68         scanf("%s", tmp);
 69         //初始化指针
 70         G->xlist[i].data = tmp[0];
 71         G->xlist[i].firstin = NULL;
 72         G->xlist[i].firstout = NULL;
 73     }
 74     
 75     //输入各弧并构造十字链表
 76     for(k=0; k<G->arcnum; k++){
 77         printf("输入第%d条弧(顶点1, 顶点2): ", k+1);
 78         memset(tmp, 0, sizeof(tmp));
 79         scanf("%s", tmp);
 80         sscanf(tmp, "%c,%c", &v1, &v2);
 81         //确定顶点v1和v2在图中的位置
 82         i = LocateVex(*G, v1);    
 83         j = LocateVex(*G, v2);
 84         //对弧结点赋值
 85         p = (ArcBox *) malloc(sizeof(ArcBox));
 86         p->tailvex = i;
 87         p->headvex = j;
 88         p->hlink = G->xlist[j].firstin;
 89         p->tlink = G->xlist[i].firstout;
 90         p->info = NULL;
 91         //完成在入弧和出弧链头的插入
 92         G->xlist[j].firstin = p;
 93         G->xlist[i].firstout = p;
 94         //若弧有相关的信息,则输入
 95         if(IncInfo){
 96             //Input(p->info);
 97         }
 98     }
 99     return 0;
100 }
101 
102 /*
103     采用十字链表的存储结构,构造图
104 */
105 int CreateGraph(OLGraph *G)
106 {
107     printf("输入图类型: +有向图(0), -有向网(1), -无向图(2), -无向网(3): ");
108     scanf("%d", &G->kind);
109     switch(G->kind){
110         case DG:
111             return CreateDG(G);
112         case DN:
113         case UDN:
114         case UDG:
115         default:
116             printf("还不支持!\n");
117             return -1;
118     }
119 }
120 
121 /*
122     输出图的信息
123 */
124 void printG(OLGraph G)
125 {
126     if(G.kind == DG){
127         printf("类型:有向图;顶点数 %d, 弧数 %d\n", G.vexnum, G.arcnum);
128     }else if(G.kind == DN){
129         printf("类型:有向网;顶点数 %d, 弧数 %d\n", G.vexnum, G.arcnum);
130     }else if(G.kind == UDG){
131         printf("类型:无向图;顶点数 %d, 弧数 %d\n", G.vexnum, G.arcnum);
132     }else if(G.kind == UDN){
133         printf("类型:无向网;顶点数 %d, 弧数 %d\n", G.vexnum, G.arcnum);
134     }
135 
136     int i = 0;
137     ArcBox *fi = NULL;
138     ArcBox *fo = NULL;
139     for(i=0; i<G.vexnum; i++){
140         printf("%c: ", G.xlist[i].data);
141         fi = G.xlist[i].firstin;
142         fo = G.xlist[i].firstout;
143         printf("(hlink=");
144         while(fi){
145 #ifdef DEBUG
146             printf("%c->%c; ", LocateVInfo(G, fi->tailvex), LocateVInfo(G, fi->headvex));
147 #else
148             printf("%d->%d; ", fi->tailvex, fi->headvex);
149 #endif
150             fi = fi->hlink;
151         }
152         printf(")\t(tlink=");
153         while(fo){
154 #ifdef DEBUG
155             printf("%c->%c; ", LocateVInfo(G, fo->tailvex), LocateVInfo(G, fo->headvex));
156 #else
157             printf("%d->%d; ", fo->tailvex, fo->headvex);
158 #endif
159             fo = fo->tlink;
160         }
161         printf(")\n");
162     }
163     return;
164 }
165 
166 int main(int argc, char *argv[])
167 {
168     OLGraph G;
169     if(CreateGraph(&G) > -1){
170         printG(G);
171     }
172     return 0;
173 }
十字链表存储结构(图)

 

代码运行

 

posted on 2018-10-02 18:21  LiveWithACat  阅读(1083)  评论(0编辑  收藏  举报