• 第1关:图的邻接矩阵存储及求邻接点操作


    • 任务要求
    • 参考答案
    • 评论2

    任务描述

    本关任务:要求从文件输入顶点和边数据,包括顶点信息、边、权值等,编写程序实现以下功能。 1)构造无向网G的邻接矩阵和顶点集,即图的存储结构为邻接矩阵。 2)输出无向网G的各顶点和邻接矩阵。 3)输出无向网G中顶点H的所有邻接顶点。

    相关知识

    图是表达“多对多”的关系的一种数据结构,由非空的有限顶点集合和有限边集合组成。将图的类型定义为枚举类型,在枚举值表中罗列:

    enum GraphKind{DG,DN,UDG,UDN}; // 有向图,有向网,无向图,无向网

    顶点集合

    每个顶点数据类型为VertexType,一个图的顶点集合用数组表示,数组下标表示顶点位置。数组内容包含顶点的信息,图的顶点集合的数据类型定义如下:

     
    
    1. #define MAX_VERTEX_NUM 20 // 最大顶点个数
    2. typedef char VertexType[16]; // 顶点类型
    3. VertexType vexs[MAX_VERTEX_NUM]; // 顶点向量

    将顶点数据类型定义为长度为16的字符数组类型,可以将表示的城市名称存储在计算机中。

    边集合

    邻接矩阵是表示顶点之间相邻关系的矩阵。设G=(V,E)是具有n顶点的图,则G的邻接矩阵是具有如下性质的n阶方阵:

    图及邻接矩阵

    网及邻接矩阵

    用邻接矩阵来表示一个具有n个顶点的图时,用邻接矩阵中的n×n个元素存储顶点间相邻关系,对于无权图,当邻接矩阵中的元素仅表示相应的边是否存在时,VRType可定义为值为01的枚举类型,0表示两个顶点之间没有边,即没有关系。对于带权图,则为权值,如果两个顶点之间没有边,则用一个很大很大的数代替。将顶点关系类型VRType定义为整型:

    typedef int VRType; // 顶点关系边的数据类型

    顶点关系边的数据类型类型,对于无权图,用1或0表示相邻否;对于带权图,则为权值。

    图的边集合的数据类型定义如下:

     
    
    1. #define INFINITY INT_MAX // 用整型最大值代替∞
    2. typedef struct
    3. {
    4. VRType adj;
    5. } ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

    说明: AcrCellAdjMatrix都是类型的名称,若有定义: AdjMatrix arcs;arcs是一个以元素类型为AcrCell20*20二维数组。上述声明与下面等同: ArcCell arcs [MAX_VERTEX_NUM][MAX_VERTEX_NUM];

    图的邻接矩阵存储表示,类型定义如下:

     
    
    1. struct MGraph
    2. {
    3. VertexType vexs[MAX_VERTEX_NUM]; // 顶点向量
    4. AdjMatrix arcs; // 邻接矩阵
    5. int vexnum, arcnum; // 图的当前顶点数和弧数
    6. GraphKind kind; // 图的种类标志
    7. };

    图的邻接矩阵表示法是图的一种顺序存储结构,优点是可以快速判断两个顶点之间是否存在边,可以快速添加边或者删除边,可以快速计算顶点度数、求邻接点的操作等;而其缺点是如果顶点之间的边比较少,会比较浪费空间。

    邻接矩阵具有如下性质: (1)图中各项点的序号确定后,图的邻接矩阵是唯一确定的; (2)无向图和无向网的邻接矩阵是一个对称矩阵; (3)无向图邻接矩阵中第i行(或第i列)的非0元素的个数即为第i个顶点的度; (4)有向图邻接矩阵中第i行非0元素的个数为第i个顶点的出度,第i列非0元素的个数为第i个顶点的入度,第i个顶点的度为第i行与第j非0元素个数之和; (5)无向图的边数等于邻接矩阵中非0元素个数之和的一半,有向图的弧数等于邻接矩阵中非0元素个数之和。

    编程要求

    根据提示,在右侧编辑器补充代码,要求从文件中输入顶点和边数据,包括顶点信息、边、权值等,编写函数实现图的基本运算:

     
    
    1. void CreateGraphF(MGraph &G);// 采用数组(邻接矩阵)表示法,由文件构造无向网G
    2. void Display(MGraph G); // 输出邻接矩阵存储表示的图G
    3. int LocateVex(MGraph G,VertexType u);//若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
    4. VertexType& GetVex(MGraph G,int v); // v是G中某个顶点的序号,返回v的值
    5. int FirstAdjVex(MGraph G,VertexType v);//v是图G中某个顶点,返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,则返回-1
    6. int NextAdjVex(MGraph G,VertexType v,VertexType w);//v是G中某个顶点,w是v的邻接顶点,返回v的(相对于w的)下一个邻接顶点的序号,若w是v的最后一个邻接顶点,则返回-1
    7. void DestroyGraph(MGraph &G); // 销毁图G

    测试说明

    平台会对你编写的代码进行测试:

    测试输入: 3 lt.txt 武汉

    输入说明: 第一行输入3,表示输入图的类型为无向网。 第二行输入文件名,该文件里保存了图的数据信息,内容如下: 6 9 武汉 上海 长沙 南京 成都 广州 武汉 长沙 9 武汉 成都 2 长沙 上海 2 长沙 南京 2 上海 南京 5 上海 广州 4 上海 成都 3 南京 广州 8 成都 广州 6

    第1行为图的顶点的个数n; 第2行为图的边的条数m; 第3行至第n+2行是n个顶点的数据; 第n+3行至第n+m+2行是m条边的数据; 最后输入一个顶点的数据

    预期输出: 无向网 6个顶点9条边。顶点依次是: 武汉 上海 长沙 南京 成都 广州 图的邻接矩阵: ∞ ∞ 9 ∞ 2 ∞ ∞ ∞ 2 5 ∞ ∞ 9 2 ∞ 2 ∞ ∞ ∞ 5 2 ∞ ∞ ∞ 2 ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ 长沙 成都

    1. #include
    2. #include
    3. #include
    4. #include
    5. typedef int VRType; // 顶点关系类型
    6. typedef char VertexType[20]; // 顶点类型
    7. // 图的数组(邻接矩阵)存储表示
    8. #define INFINITY INT_MAX // 用整型最大值代替∞
    9. #define MAX_VERTEX_NUM 20 // 最大顶点个数
    10. typedef enum{DG,DN,UDG,UDN}GraphKind; // {有向图,有向网,无向图,无向网}
    11. typedef struct
    12. {
    13. VRType adj; // 顶点关系类型。对无权图,用1(是)或0(否)表示相邻否;对带权图,则为权值
    14. }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 二维数组
    15. typedef struct // 图的数组(邻接矩阵)存储
    16. {
    17. VertexType vexs[MAX_VERTEX_NUM]; // 顶点向量
    18. AdjMatrix arcs; // 邻接矩阵
    19. int vexnum,arcnum; // 图的当前顶点数和弧数
    20. GraphKind kind; // 图的种类标志
    21. }MGraph;
    22. void visit(VertexType i);
    23. void CreateGraphF(MGraph &G);// 采用数组(邻接矩阵)表示法,由文件构造无向网G
    24. void Display(MGraph G); // 输出邻接矩阵存储表示的图G
    25. int LocateVex(MGraph G,VertexType u);//若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
    26. VertexType* GetVex(MGraph G,int v); // v是G中某个顶点的序号,返回v的值
    27. int FirstAdjVex(MGraph G,VertexType v);//v是图G中某个顶点,返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,则返回-1
    28. int NextAdjVex(MGraph G,VertexType v,VertexType w);//v是G中某个顶点,w是v的邻接顶点,返回v的(相对于w的)下一个邻接顶点的序号,若w是v的最后一个邻接顶点,则返回-1
    29. void DestroyGraph(MGraph &G); // 销毁图G
    30. int main()
    31. {
    32. MGraph g;
    33. VertexType v1,v2;
    34. CreateGraphF(g); // 利用数据文件创建邻接矩阵表示的图
    35. Display(g); // 输出图
    36. int i,j,k,n;
    37. //printf("请输入顶点的值: ");
    38. scanf("%s",v1);
    39. //printf("输出图G中顶点%s的所有邻接顶点: ",v1);
    40. k=FirstAdjVex(g,v1);
    41. while(k!=-1)
    42. {
    43. strcpy(v2, g.vexs[k] );
    44. visit(v2);
    45. k=NextAdjVex(g,v1,v2);
    46. }
    47. printf("\n");
    48. return 0;
    49. }
    50. void visit(VertexType i)
    51. {
    52. printf("%s ",i);
    53. }
    54. void CreateGraphF(MGraph &G)
    55. {
    56. // 采用数组(邻接矩阵)表示法,由文件构造无向网G
    57. /********** Begin **********/
    58. int i,j,k,w;
    59. char filename[13];
    60. VertexType va,vb;
    61. FILE * graphlist;
    62. scanf("%d",&G.kind);
    63. scanf("%s",filename);
    64. graphlist=fopen(filename,"r");
    65. fscanf(graphlist,"%d",&G.vexnum);
    66. fscanf(graphlist,"%d",&G.arcnum);
    67. for(i=0;i
    68. fscanf(graphlist,"%s",G.vexs[i]);
    69. for(i=0;i
    70. for(j=0;j
    71. if(G.kind%2)
    72. G.arcs[i][j].adj=INFINITY;
    73. else
    74. G.arcs[i][j].adj=0;
    75. }
    76. for(k=0;k
    77. if(G.kind%2)
    78. fscanf(graphlist,"%s%s%d",va,vb,&w);
    79. else
    80. fscanf(graphlist,"%s%s",va,vb);
    81. i=LocateVex(G,va);
    82. j=LocateVex(G,vb);
    83. if(G.kind==0)
    84. G.arcs[i][j].adj=1;
    85. else if(G.kind==1)
    86. G.arcs[i][j].adj=w;
    87. else if(G.kind==2)
    88. G.arcs[i][j].adj=G.arcs[j][i].adj=1;
    89. else
    90. G.arcs[i][j].adj=G.arcs[j][i].adj=w;
    91. }
    92. fclose(graphlist);
    93. /********** End **********/
    94. }
    95. void Display(MGraph G)
    96. {
    97. // 输出邻接矩阵存储表示的图G
    98. /********** Begin **********/
    99. int i,j;
    100. switch(G.kind){
    101. case DG:printf("有向图\n");break;
    102. case DN:printf("有向网\n");break;
    103. case UDG:printf("无向图\n");break;
    104. case UDN:printf("无向网\n");
    105. }
    106. printf("%d个顶点%d条边。顶点依次是: ",G.vexnum,G.arcnum);
    107. for(i=0;i
    108. printf("%s ",G.vexs[i]);
    109. printf("\n图的邻接矩阵:\n");
    110. for(i=0;i
    111. for(j=0;j
    112. if(G.kind%2){
    113. if(G.arcs[i][j].adj==INFINITY)
    114. printf("%s\t","∞");
    115. else
    116. printf("%d\t",G.arcs[i][j].adj);
    117. }else
    118. printf("%d\t",G.arcs[i][j].adj);
    119. printf("\n");
    120. }
    121. /********** End **********/
    122. }
    123. int LocateVex(MGraph G,VertexType u)
    124. {
    125. //初始条件:图G存在,u和G中顶点有相同特征
    126. // 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
    127. /********** Begin **********/
    128. int i;
    129. for(i=0;i
    130. if(strcmp(u,G.vexs[i])==0) return i;
    131. return -1;
    132. /********** Begin **********/
    133. }
    134. VertexType* GetVex(MGraph G,int v)
    135. {
    136. // 初始条件:图G存在,v是G中某个顶点的序号。操作结果:返回v的值
    137. /********** Begin **********/
    138. if(v>=G.vexnum || v<0)
    139. exit(0);
    140. return &(G.vexs[v]);
    141. /********** End **********/
    142. }
    143. int FirstAdjVex(MGraph G,VertexType v)
    144. {
    145. // 初始条件:图G存在,v是G中某个顶点
    146. // 操作结果:返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,则返回-1
    147. /********** Begin **********/
    148. int i,j,k;
    149. if(G.kind%2)
    150. j=INFINITY;
    151. else
    152. j=0;
    153. k=LocateVex(G,v);
    154. for(i=0;i
    155. if(G.arcs[k][i].adj!=j)
    156. return i;
    157. return -1;
    158. /********** End **********/
    159. }
    160. int NextAdjVex(MGraph G,VertexType v,VertexType w)
    161. {
    162. // 初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点
    163. // 操作结果:返回v的(相对于w的)下一个邻接顶点的序号,若w是v的最后一个邻接顶点,则返回-1
    164. /********** Begin **********/
    165. int i,j,k1,k2;
    166. if(G.kind%2)
    167. j=INFINITY;
    168. else
    169. j=0;
    170. k1=LocateVex(G,v);
    171. k2=LocateVex(G,w);
    172. for(i=k2+1;i
    173. if(G.arcs[k1][i].adj!=j)
    174. return i;
    175. return -1;
    176. /********** End **********/
    177. }
    178. void DestroyGraph(MGraph &G)
    179. { // 初始条件:图G存在。操作结果:销毁图G
    180. /********** Begin **********/
    181. int i,j,k=0;
    182. if(G.kind%2)
    183. k=INFINITY;
    184. G.vexnum=0;
    185. G.arcnum=0;
    186. /********** End **********/
    187. }

    输出说明: 第一行输出图的类型。 第二行起输出图的顶点和边的数据信息。 最后一行输出输入顶点的所有邻接点。

  • 相关阅读:
    node的web编程
    (C语言)成绩统计
    CPSC认证是什么意思?CPSC主要测什么?
    【Mycat】Mycat主从复制
    在express中使用session认证
    【POST请求-腾讯翻译君-爬虫案例】
    QCSPCChart for Java R3x0 Crack
    Unity技术手册 - 干扰/噪音/杂波(Noise)子模块
    刷完HashMap源码,我们一起进大厂
    2024Java springboot mybatis-flex 根据数据表时间开启定时任务
  • 原文地址:https://blog.csdn.net/toptopniba/article/details/134534404