图的表示法

太过爱你忘了你带给我的痛 2022-08-23 09:56 330阅读 0赞

图的分类

图表示一种多对多的关系。

图的概念

图由顶点和边组成。可以无边,但至少有一个顶点。

  • 一组顶点,通常有V(vetex)表示顶点的集合
  • 一组边,通常用E(edge)表示边的集合

图可以分为有向图和无向图

  • (v,w)表示无向边,即v和w是互通的
  • <v,w)表示有向边,边始于v, 终于w

图可以分为有权图和无权图

  • 有权图:每条边都有权重值,通常是一个数字
  • 无权图:每条边都没有权重,通常可以理解为权重为1

图又可以分为连通图和非连通图

  • 连通图:所有的顶点都有路径相连
  • 非连通图:存在某两个顶点没有路径相连

图中的顶点有度的概念

  • 度:所有和它连接点的个数之和
  • 出度:存在于有向图中,所有接入该点的边数之和
  • 入度:存在于有向图中,所有从接出该点的边数之和

图的表示方法

要表示一个图G=(V,E)(注:V:vertex、E:edge),有两种方法,即邻接表和邻接矩阵。这两种方法既可以用于有向图,也可以用于无向图

  1. // 图1,无向图
  2. 1 ----- 2
  3. | | \
  4. | | / 3
  5. 5 ----- 4

邻接表

邻接表表示法通常表示稀疏图(图中 |E| 远小于 |V|^2)比较紧凑。

  1. // 邻接表数据结构表示无向图
  2. // 定义图中最多100个节顶点
  3. #define MAX 100
  4. // 邻接表中的顶点定义
  5. typedef struct Vertex
  6. {
  7. int v;
  8. struct Vertex *next;
  9. } Vertex;
  10. // 邻接表
  11. Vertex Adj[MAX];
  12. // 创建顶点
  13. Vertex* makeVertex(int v)
  14. {
  15. Vertex *pVertex = (Vertex*) malloc(sizeof(Vertex));
  16. pVertex->v = v;
  17. pVertex->next = NULL;
  18. return pVertex;
  19. }
  20. // 删除顶点
  21. void destroyVertex(Vertex *pVertex)
  22. {
  23. free(pVertex);
  24. }
  25. // 完整代码
  26. #include <stdio.h>
  27. #include <malloc.h>
  28. #define MAX 100
  29. typedef struct Vertex
  30. {
  31. int v;
  32. struct Vertex *next;
  33. } Vertex;
  34. Vertex Adj[MAX];
  35. Vertex* makeVertex(int v)
  36. {
  37. Vertex *pVertex = (Vertex*) malloc(sizeof(Vertex));
  38. pVertex->v = v;
  39. pVertex->next = NULL;
  40. return pVertex;
  41. }
  42. void destroyVertex(Vertex *pVertex)
  43. {
  44. free(pVertex);
  45. }
  46. // 初始化图
  47. void initGraph()
  48. {
  49. printf("input edges:\nlike 1,2\n-1,-1\n");
  50. int v1 = 0, v2 = 0;
  51. while (1){
  52. scanf("%d,%d", &v1, &v2);
  53. // 输入-1,-1表示输入结束
  54. if (v1 == -1 && v2 == -1)
  55. break;
  56. Adj[v1].v = v1;
  57. Vertex *pVertex = &Adj[v1];
  58. while ( pVertex->next ) {
  59. pVertex = pVertex->next;
  60. }
  61. pVertex->next = makeVertex(v2);
  62. }
  63. }
  64. // 打印当前图
  65. void printGraph(int n)
  66. {
  67. for (int i = 1; i <= n; i++) {
  68. printf("%d", Adj[i].v);
  69. Vertex *pVertex = Adj[i].next;
  70. while (pVertex) {
  71. printf("--%d", pVertex->v);
  72. pVertex = pVertex->next;
  73. }
  74. printf("\n");
  75. }
  76. }
  77. // 销毁图中的节点
  78. void uninitGraph(int n) {
  79. for (int i = 1; i <= n; i++) {
  80. Vertex *pVertex = Adj[i].next;
  81. Adj[i].next = NULL;
  82. while (pVertex) {
  83. Vertex *pTemp = pVertex->next;
  84. destroyVertex(pVertex);
  85. pVertex = pTemp;
  86. }
  87. printf("destroy vertex[%d]\n", i);
  88. }
  89. }
  90. int main()
  91. {
  92. int n = 0;
  93. printf("input vertex's number\n");
  94. scanf("%d", &n);
  95. initGraph();
  96. printGraph(n);
  97. uninitGraph(n);
  98. printGraph(n);
  99. return 0;
  100. }
  101. // 执行方式
  102. input vertex's number
  103. 5
  104. 1,2
  105. 1,5
  106. ...
  107. -1,-1 // 结束输入

邻接表的长度

若G是一个有向图,则所有邻接表的长度之和为 |E|。
若G是一个无向图,则所有邻接表的长度之和为 2|E|。
无论有向图还是无向图,邻接表需要的存储空间为O(V+E)。

加权图

图的每条边有着相应权值。
设G=(V,E)是一个加权函数为w的加权图。对每一条边(u,v)且(u,v)属于E,权值为w(u,v)和顶点v一起存储在u的邻接表中。

  1. typedef struct Vertex
  2. {
  3. int v; // 顶点
  4. int w; // 加权值
  5. struct Vertex *next;
  6. } Vertex;

邻接矩阵

邻接矩阵表示法通常用于表示稠密图(图中|E| 接近于 |V|^2)或必须很快判别两个顶点是否存在连接边时使用

  1. // 邻接矩阵表示无向图
  2. #define MAX 100
  3. int G[MAX][MAX] = {0};
  4. // 完整代码
  5. #include <stdio.h>
  6. #define MAX 100
  7. int G[MAX][MAX] = {0};
  8. // 初始化图
  9. void initGraph()
  10. {
  11. printf("input edges:\nlike 1,2\n");
  12. int v1 = 0, v2 = 0;
  13. while (1){
  14. scanf("%d,%d", &v1, &v2);
  15. if (v1 == -1 && v2 == -1)
  16. break;
  17. G[v1][v2] = 1;
  18. G[v2][v1] = 1;
  19. }
  20. }
  21. // 打印图
  22. void printGraph(int n)
  23. {
  24. for (int i = 1; i <= n; i++) {
  25. printf("%d", i);
  26. for (int j = 1; j <= n; j++) {
  27. if (G[i][j] == 1) {
  28. printf("--%d", j);
  29. }
  30. }
  31. printf("\n");
  32. }
  33. }
  34. int main()
  35. {
  36. int n = 0;
  37. printf("input vertex's number\n");
  38. scanf("%d", &n);
  39. initGraph();
  40. printGraph(n);
  41. return 0;
  42. }

邻接矩阵的特点

一个图的邻接矩阵表示需要占用O(V^2)的存储空间,它与图中的边数多少是无关的。

无向图的邻接矩阵A就是它自己的转置矩阵:A=A^T。在某些应用中只需要存储临街觉着呢的对角线及对角线以上的部分,图所占的存储空间几乎可以减少一半。

邻接矩阵的也可以用来表示加权图。矩阵中相应的元素可以存储边的权值,如果边不存在就用0或无限大的值来表示权值。

如果一个图不是加权的,邻接矩阵的每个元素只用一个二进制位,而不必用一个字的空间。

发表评论

表情:
评论列表 (有 0 条评论,330人围观)

还没有评论,来说两句吧...

相关阅读