1. /*
    2. 采用邻接表的方式存储图
    3. 分析:
    4. 采用邻接表相对于邻接矩阵来说更节省存储空间,这里我们需要两个数据结构:
    5. ①顶点表结构:包括顶点信息及指向第一个邻接点的头指针
    6. ②边表结构:包括该邻接点域(在数组中的下标)、权值及下一个邻接点指针
    7. ③一个数组,用于存储所有顶点,因为数组的随机存储特性,方便我们查找
    8. ④图结构:包括顶点数组及顶点数、边数
    9. 具体创建流程:
    10. 首先我们需要输入图的顶点数和边数,将其存入图结构中,并由输入的顶点数依次输入顶点信息,并将第一个邻接点的头指针
    11. 置位NULL,这是建立顶点表的流程;
    12. 其次我们需要建立边表,根据输入的边个数,依次输入边(vi,vj)的顶点序号,再采取头插法进行插入,若是无向图则需要
    13. 重复反向依次设置,至此,图的邻接表结构建立完成。
    14. */
    15. #define _CRT_SECURE_NO_WARNINGS
    16. #define MAXSIZE 100
    17. #define TYPE int
    18. typedef struct EdgeNode {//边表结点
    19. int index;//该边所指向的顶点的位置,在顶点数组里面的位置信息
    20. int weight;//权值
    21. EdgeNode *next;//下一个邻接边
    22. }EdgeNode;
    23. typedef struct VertexNode {//顶点表节点
    24. TYPE info;//顶点信息
    25. EdgeNode *firstEdge;//指向第一条依附该顶点的边的指针
    26. }VertexNode, Adjlist[MAXSIZE];
    27. typedef struct {
    28. Adjlist adjlist;//顶点数组
    29. int numE, numV;//边数、顶点数
    30. }ALGraph;
    31. #include <stdio.h>
    32. #include <stdlib.h>
    33. void createGraph(ALGraph *G) {
    34. int e, v, vi, vj, w;
    35. printf("请输入图的边数与结点数(以空格分开):");
    36. scanf("\n%d %d", &e, &v);
    37. G->numE = e;
    38. G->numV = v;
    39. printf("请依次输入顶点信息:\n");
    40. for (int i = 0; i < G->numV; i++) {
    41. printf("请输入第%d个结点信息:", i + 1);
    42. scanf("\n%c", &G->adjlist[i].info);
    43. G->adjlist[i].firstEdge = NULL;
    44. //G->adjlist[i].firstEdge->index = -1;
    45. }
    46. printf("请输入边表信息:\n");
    47. for (int i = 0; i < G->numE; i++) {
    48. printf("请输入边(vi,vj)的顶点序号及其权值(以空格分开):");
    49. scanf("%d %d %d", &vi, &vj, &w);
    50. //若是无向图则需要两个顶点进行操作,采用头插法
    51. EdgeNode *e = (EdgeNode *)malloc(sizeof(EdgeNode *));
    52. e->index = vj - 1;//数组下标要减一
    53. e->weight = w;
    54. e->next = G->adjlist[vi - 1].firstEdge;
    55. G->adjlist[vi - 1].firstEdge = e;
    56. /*EdgeNode *ed = (EdgeNode *)malloc(sizeof(EdgeNode *));
    57. ed->index = vi - 1;
    58. ed->weight = w;
    59. ed->next = G->adjlist[vj - 1].firstEdge;
    60. G->adjlist[vj - 1].firstEdge = ed;*/
    61. }
    62. }
    63. void createGraphInFile(ALGraph *G) {//从文件中读取我们的图的数据,包括边数,节点数,对应关系
    64. FILE *fp;//创建文件指针
    65. char ev[4] = {};
    66. char numE[3] = { 0 };//顶点,边个数信息
    67. char numV[3] = { 0 };//顶点,边个数信息
    68. char arc[6] = { 0 };//边信息
    69. char *vertex;//顶点信息,名称
    70. fp = fopen("graph.txt", "r");//打开文件
    71. if (fp == NULL) {
    72. printf("该文件无法打开!");
    73. return;
    74. }
    75. fscanf(fp, "%hu %hu", numE, numV);//读取第一行
    76. G->numE = numE[0];
    77. G->numV = numV[0];
    78. vertex = (char *)malloc(sizeof(char*)*G->numV);//这是用来存储顶点信息的数组(顶点的名字)
    79. for (int i = 0; i <= G->numE; i++) {//开始获取后面的信息
    80. if (i == 0) {//此时,根据我们文件的结构,第二行是顶点信息
    81. fgets(ev, 4, fp);//获取回车符,上一次fgets后会停在回车符那儿
    82. fgets(vertex,G->numV*2,fp);//这里获取顶点信息
    83. int w = 0;//用一个计数器,保证adjlist依次存储顶点
    84. for (int j = 0; j < G->numV*2;j++) {//因为有空格,所以让j<G->numV*2
    85. if (vertex[j]==32) {//是空格,不进行操作
    86. continue;
    87. }
    88. else {//开始赋值
    89. G->adjlist[w].info = vertex[j];
    90. G->adjlist[w].firstEdge = NULL;
    91. w++;
    92. }
    93. }
    94. }
    95. else {//开始依次存储边信息
    96. fgets(ev, 4, fp);//同样先吃掉换行符
    97. fgets(arc, 6, fp);//读取该行的边信息
    98. EdgeNode *e = (EdgeNode *)malloc(sizeof(struct EdgeNode ));
    99. e->index = atoi(&arc[2]) - 1;//数组下标要减一
    100. e->weight = atoi(&arc[4]);
    101. e->next = G->adjlist[atoi(&arc[0])-1].firstEdge;//采用头插法
    102. G->adjlist[atoi(&arc[0])-1].firstEdge = e;
    103. //下面与上面相似,目的在于构建无向图
    104. //EdgeNode *otherE = (EdgeNode *)malloc(sizeof(struct EdgeNode ));
    105. //otherE->index = atoi(&arc[0]) - 1;//数组下标要减一
    106. //otherE->weight = atoi(&arc[4]);
    107. //otherE->next = G->adjlist[atoi(&arc[2]) - 1].firstEdge;
    108. //G->adjlist[atoi(&arc[2]) - 1].firstEdge = otherE;
    109. }
    110. }
    111. fclose(fp);
    112. }
    113. void dispGraph(ALGraph *G) {//将图用邻接表的形式展示出来
    114. for (int i = 0; i < G->numV; i++) {
    115. int j = i;
    116. printf("%c-->", G->adjlist[j].info);
    117. EdgeNode *p = G->adjlist[j].firstEdge;
    118. while (p) {
    119. printf("(%d)%c-->", p->weight, G->adjlist[p->index].info);
    120. p = p->next;
    121. }
    122. printf("^\n");
    123. }
    124. }
    125. //int main() {
    126. // ALGraph G;
    127. // createGraphInFile(&G);
    128. // dispGraph(&G);
    129. // return 0;
    130. //}