当前位置:   article > 正文

数据结构(6_2_3)——十字链表法和多重领接表

数据结构(6_2_3)——十字链表法和多重领接表

十字链表存储有向图

橙色入度,绿色出度

 代码示例:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. // 定义十字链表节点结构体
  4. typedef struct OLNode {
  5. int row; // 行号
  6. int col; // 列号
  7. int value; // 节点值
  8. struct OLNode* right; // 指向右边节点的指针
  9. struct OLNode* down; // 指向下方节点的指针
  10. } OLNode, * OLink;
  11. // 定义十字链表的头节点结构体
  12. typedef struct {
  13. OLink* row_head; // 行表头指针数组
  14. OLink* col_head; // 列表头指针数组
  15. int m, n, len; // 矩阵的行数、列数和非零元素的个数
  16. } CrossList;
  17. // 创建十字链表
  18. CrossList CreateCrossList(int m, int n) {
  19. CrossList M;
  20. M.m = m;
  21. M.n = n;
  22. M.len = 0;
  23. // 初始化行和列的头指针数组
  24. M.row_head = (OLink*)malloc((m + 1) * sizeof(OLink));
  25. M.col_head = (OLink*)malloc((n + 1) * sizeof(OLink));
  26. if (!M.row_head || !M.col_head) {
  27. exit(1); // 内存分配失败
  28. }
  29. for (int i = 1; i <= m; i++) {
  30. M.row_head[i] = NULL;
  31. }
  32. for (int j = 1; j <= n; j++) {
  33. M.col_head[j] = NULL;
  34. }
  35. return M;
  36. }
  37. // 向十字链表插入元素
  38. void Insert(CrossList* M, int i, int j, int value) {
  39. if (i > M->m || j > M->n || value == 0) {
  40. return; // 插入位置不合法或值为0
  41. }
  42. // 创建新节点
  43. OLNode* newNode = (OLNode*)malloc(sizeof(OLNode));
  44. newNode->row = i;
  45. newNode->col = j;
  46. newNode->value = value;
  47. newNode->right = NULL;
  48. newNode->down = NULL;
  49. // 插入行
  50. if (M->row_head[i] == NULL) {
  51. M->row_head[i] = newNode;
  52. }
  53. else {
  54. OLNode* current = M->row_head[i];
  55. while (current->right && current->right->col < j) {
  56. current = current->right;
  57. }
  58. newNode->right = current->right;
  59. current->right = newNode;
  60. }
  61. // 插入列
  62. if (M->col_head[j] == NULL) {
  63. M->col_head[j] = newNode;
  64. }
  65. else {
  66. OLNode* current = M->col_head[j];
  67. while (current->down && current->down->row < i) {
  68. current = current->down;
  69. }
  70. newNode->down = current->down;
  71. current->down = newNode;
  72. }
  73. M->len++; // 更新非零元素个数
  74. }
  75. // 从十字链表删除元素
  76. void Delete(CrossList* M, int i, int j) {
  77. if (i > M->m || j > M->n) {
  78. return; // 位置不合法
  79. }
  80. // 查找要删除的节点
  81. OLNode* p = M->row_head[i];
  82. while (p && p->col < j) {
  83. p = p->right;
  84. }
  85. if (p && p->col == j) {
  86. // 删除行中的节点
  87. if (p == M->row_head[i]) {
  88. M->row_head[i] = p->right;
  89. }
  90. else {
  91. OLNode* q = M->row_head[i];
  92. while (q->right != p) {
  93. q = q->right;
  94. }
  95. q->right = p->right;
  96. }
  97. // 删除列中的节点
  98. if (p == M->col_head[j]) {
  99. M->col_head[j] = p->down;
  100. }
  101. else {
  102. OLNode* q = M->col_head[j];
  103. while (q->down != p) {
  104. q = q->down;
  105. }
  106. q->down = p->down;
  107. }
  108. free(p); // 释放节点内存
  109. M->len--; // 更新非零元素个数
  110. }
  111. }
  112. // 在十字链表中查找元素
  113. OLNode* Find(CrossList M, int i, int j) {
  114. if (i > M.m || j > M.n) {
  115. return NULL; // 位置不合法
  116. }
  117. OLNode* p = M.row_head[i];
  118. while (p && p->col < j) {
  119. p = p->right;
  120. }
  121. if (p && p->col == j) {
  122. return p; // 找到元素,返回节点指针
  123. }
  124. else {
  125. return NULL; // 未找到元素
  126. }
  127. }
  128. // 打印十字链表
  129. void PrintCrossList(CrossList M) {
  130. printf("十字链表如下:\n");
  131. for (int i = 1; i <= M.m; i++) {
  132. OLNode* p = M.row_head[i];
  133. while (p) {
  134. printf("(%d, %d, %d) ", p->row, p->col, p->value);
  135. p = p->right;
  136. }
  137. printf("\n");
  138. }
  139. }
  140. // 释放十字链表
  141. void FreeCrossList(CrossList* M) {
  142. for (int i = 1; i <= M->m; i++) {
  143. OLNode* p = M->row_head[i];
  144. while (p) {
  145. OLNode* q = p;
  146. p = p->right;
  147. free(q);
  148. }
  149. }
  150. free(M->row_head);
  151. free(M->col_head);
  152. }
  153. int main() {
  154. int m = 3, n = 4; // 定义一个3行4列的稀疏矩阵
  155. CrossList M = CreateCrossList(m, n); // 创建十字链表
  156. // 插入元素
  157. Insert(&M, 1, 2, 12);
  158. Insert(&M, 1, 4, 9);
  159. Insert(&M, 3, 1, -3);
  160. Insert(&M, 3, 3, 14);
  161. // 打印十字链表
  162. PrintCrossList(M);
  163. // 删除元素
  164. Delete(&M, 1, 2);
  165. // 再次打印十字链表
  166. printf("删除元素后的十字链表:\n");
  167. PrintCrossList(M);
  168. // 释放十字链表
  169. FreeCrossList(&M);
  170. return 0;
  171. }

 十字链表法性能分析

 

领接矩阵、邻接表存储无向图的缺点

邻接多重表存储无向图 

优点:

每一条边只对应一个边结点,没有冗余数据,删除结点或者删除边的时候会方便很多

 

 代码示例:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. // 定义邻接多重表的边节点结构体
  4. typedef struct EdgeNode {
  5. int ivex; // 边的起点
  6. int jvex; // 边的终点
  7. struct EdgeNode* ilink; // 指向起点相同的下一条边
  8. struct EdgeNode* jlink; // 指向终点相同的下一条边
  9. int mark; // 标记边是否被访问过
  10. } EdgeNode;
  11. // 定义邻接多重表的顶点节点结构体
  12. typedef struct VertexNode {
  13. int data; // 顶点数据
  14. EdgeNode* firstedge; // 指向第一条依附于该顶点的边
  15. } VertexNode;
  16. // 定义邻接多重表结构体
  17. typedef struct {
  18. VertexNode* vertices; // 顶点表
  19. int vexnum, edgenum; // 顶点数和边数
  20. }AMLGraph;
  21. // 创建邻接多重表
  22. AMLGraph CreateAMLGraph(int vexnum, int edgenum) {
  23. AMLGraph graph;
  24. graph.vexnum = vexnum;
  25. graph.edgenum = edgenum;
  26. // 初始化顶点表
  27. graph.vertices = (VertexNode*)malloc(vexnum * sizeof(VertexNode));
  28. if (!graph.vertices) {
  29. exit(1); // 内存分配失败
  30. }
  31. for (int i = 0; i < vexnum; i++) {
  32. graph.vertices[i].data = i;
  33. graph.vertices[i].firstedge = NULL;
  34. }
  35. return graph;
  36. }
  37. // 插入边
  38. void InsertEdge(AMLGraph* graph, int ivex, int jvex) {
  39. // 创建边节点
  40. EdgeNode* newEdge = (EdgeNode*)malloc(sizeof(EdgeNode));
  41. newEdge->ivex = ivex;
  42. newEdge->jvex = jvex;
  43. newEdge->ilink = graph->vertices[ivex].firstedge;
  44. newEdge->jlink = graph->vertices[jvex].firstedge;
  45. newEdge->mark = 0;
  46. // 插入到顶点ivex的边表
  47. graph->vertices[ivex].firstedge = newEdge;
  48. // 插入到顶点jvex的边表
  49. graph->vertices[jvex].firstedge = newEdge;
  50. }
  51. // 删除边
  52. void DeleteEdge(AMLGraph* graph, int ivex, int jvex) {
  53. EdgeNode* p = graph->vertices[ivex].firstedge;
  54. EdgeNode* pre = NULL;
  55. while (p && (p->ivex != ivex || p->jvex != jvex)) {
  56. pre = p;
  57. if (p->ivex == ivex) {
  58. p = p->ilink;
  59. }
  60. else {
  61. p = p->jlink;
  62. }
  63. }
  64. if (p) {
  65. if (pre) {
  66. if (p->ivex == ivex) {
  67. pre->ilink = p->ilink;
  68. }
  69. else {
  70. pre->jlink = p->jlink;
  71. }
  72. }
  73. else {
  74. if (p->ivex == ivex) {
  75. graph->vertices[ivex].firstedge = p->ilink;
  76. }
  77. else {
  78. graph->vertices[jvex].firstedge = p->jlink;
  79. }
  80. }
  81. free(p);
  82. }
  83. }
  84. // 查找顶点
  85. VertexNode* FindVertex(AMLGraph graph, int data) {
  86. for (int i = 0; i < graph.vexnum; i++) {
  87. if (graph.vertices[i].data == data) {
  88. return &graph.vertices[i];
  89. }
  90. }
  91. return NULL;
  92. }
  93. // 打印邻接多重表
  94. void PrintAMLGraph(AMLGraph graph) {
  95. printf("邻接多重表如下:\n");
  96. for (int i = 0; i < graph.vexnum; i++) {
  97. EdgeNode* p = graph.vertices[i].firstedge;
  98. while (p) {
  99. int ivex = p->ivex;
  100. printf("(%d, %d) ", ivex, jvex);
  101. // 根据当前顶点,决定移动到ilink还是jlink
  102. if (ivex == i) {
  103. p = p->ilink;
  104. }
  105. else {
  106. p = p->jlink;
  107. }
  108. }
  109. printf("\n");
  110. }
  111. }
  112. // 释放邻接多重表
  113. void FreeAMLGraph(AMLGraph* graph) {
  114. for (int i = 0; i < graph->vexnum; i++) {
  115. EdgeNode* p = graph->vertices[i].firstedge;
  116. while (p) {
  117. EdgeNode* q = p;
  118. p = p->ilink;
  119. free(q);
  120. }
  121. }
  122. free(graph->vertices);
  123. }
  124. int main() {
  125. int vexnum = 4; // 定义顶点数为4
  126. int edgenum = 5; // 定义边数为5
  127. AMLGraph graph = CreateAMLGraph(vexnum, edgenum); // 创建邻接多重表
  128. // 插入边
  129. InsertEdge(&graph, 0, 1);
  130. InsertEdge(&graph, 0, 2);
  131. InsertEdge(&graph, 1, 2);
  132. InsertEdge(&graph, 1, 3);
  133. InsertEdge(&graph, 2, 3);
  134. // 打印邻接多重表
  135. PrintAMLGraph(graph);
  136. // 删除边
  137. DeleteEdge(&graph, 1, 2);
  138. // 再次打印邻接多重表
  139. printf("删除边后的邻接多重表:\n");
  140. PrintAMLGraph(graph);
  141. // 释放邻接多重表
  142. FreeAMLGraph(&graph);
  143. return 0;
  144. }


总结:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/1014444
推荐阅读
相关标签
  

闽ICP备14008679号