一般链表实现集合运算(C语言)

落日映苍穹つ 2023-05-29 03:45 104阅读 0赞

一般链表实现集合运算(C语言)

最近在学习数据结构,遇到以下问题:

假设集合A = (c, b, e, g, f, d),B = (a, b, n, f),利用一般线性链表实现集合运算(A-B)∪(B-A)。

分析:

上面的问题只要是考察怎样应用链表,熟悉链表的操作,对链表有更加理性的认识。题目理解:题目的意思是将A和B中相同的元素删除,不同的元素插入的到A中,或者另外创建一个链表来存储。知道题目要求之后下面来提供实现思路:

思路:

1、根据链表的特点,实现它的基本功能(增、删、改、查)。
2、在主函数中创建两个链表来存储集合A和B。
3、题目实现函数:通过使用指针来遍历A和B如果发现相同元素则进行删除,如果没有相同元素则添加。

下面给出示例代码:

  1. /** * @Author 明志 * @Detail 实现集合运算(A-B)∪(B-A) * @DateTime 2019-11-02 * @Tools sublime text3 + gcc */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <malloc.h>
  5. typedef char ElemType; //声明元素类型
  6. //声明单链表的存储结构
  7. typedef struct LNode
  8. {
  9. ElemType data;
  10. struct LNode* next;
  11. }LNode, *LinkList;
  12. //初始化单链表
  13. void InitList(LinkList* L) //注意:这里的L是二级指针
  14. {
  15. *L = (LinkList)malloc(sizeof(LNode)); //分配空间
  16. if (!(*L))
  17. {
  18. printf("the allocation space error!");
  19. exit(0);
  20. }
  21. (*L)->next = NULL;
  22. }
  23. //销毁单链表
  24. void DestroyList(LinkList *L)
  25. {
  26. LinkList q;
  27. while (*L)
  28. {
  29. q = (*L)->next;
  30. free(*L); //释放头结点
  31. *L = q; //L指向原首元节点,实现头结点
  32. }
  33. }
  34. //将单链表重置为空表
  35. void ClearList(LinkList L)
  36. {
  37. LinkList p = L->next; //p指向第一个结点
  38. L->next = NULL; //头结点指针域为空
  39. DestroyList(&p); //销毁p所指向的单链表
  40. }
  41. //判断单链表是否为空表
  42. int ListEmpty(LinkList L)
  43. {
  44. if (L->next) //非空
  45. {
  46. return 0;
  47. }
  48. else
  49. {
  50. return 1;
  51. }
  52. }
  53. //返回L中的数据元素个数
  54. int ListLength(LinkList L)
  55. {
  56. int i = 0;
  57. LinkList p = L->next; //p指向第一个结点
  58. while (p)
  59. {
  60. i++;
  61. p = p->next; //p指向下一个结点
  62. }
  63. return i;
  64. }
  65. //获取单链表中的第i个元素
  66. int GetElem(LinkList L, int i, ElemType *e)
  67. {
  68. int j = 1;
  69. LinkList p = L->next; //p指向第一个结点
  70. while (p && j < i)
  71. {
  72. j++; //计数器加一
  73. p = p->next; //p指向下一个结点
  74. }
  75. if ((!p) || (j > i)) //结点不存在
  76. {
  77. return 0;
  78. }
  79. *e = p->data; //获取第i个元素
  80. return 1;
  81. }
  82. //返回L中第一个与e存在关系的元素的位置
  83. int LocateElem(LinkList L, ElemType e, int(*compare)(ElemType, ElemType))
  84. {
  85. int i = 0;
  86. LinkList p = L->next; //p指向第一个结点
  87. while (p) //未到表尾
  88. {
  89. i++;
  90. if (compare(p->data, e)) //找出数据元素
  91. {
  92. return i;
  93. }
  94. p = p->next; //p指向下一个结点
  95. }
  96. return 0; //满足关系的数据元素不存在
  97. }
  98. //比较两个元素是否相等
  99. int ListCompare(ElemType e1, ElemType e2)
  100. {
  101. if (e1 == e2)
  102. {
  103. return 1;
  104. }
  105. else
  106. {
  107. return 0;
  108. }
  109. }
  110. //在带头结点的单链表L中第i个位置之前插入元素e
  111. int ListInsert(LinkList L, int i, ElemType e)
  112. {
  113. int j = 0;
  114. LinkList s, p = L; //p指向头结点
  115. while (p && j < i - 1) //寻找第i - 1个结点
  116. {
  117. j++;
  118. p = p->next; //p指向下一个结点
  119. }
  120. if (!p || j > i - 1)
  121. {
  122. return -1; //插入失败
  123. }
  124. s = (LinkList)malloc(sizeof(LNode)); //生成新节点,以下将其插入L中
  125. s->data = e; //将e赋值给新节点
  126. s->next = p->next; //新节点指向原第i个结点
  127. p->next = s; //原第i-1个结点指向新节点
  128. return 1; //成功插入
  129. }
  130. //在单链表中删除第i个元素并且用e返回
  131. int ListDelete(LinkList L, int i, ElemType *e)
  132. {
  133. int j = 0;
  134. LinkList q, p = L;
  135. while (p->next && j < i - 1)
  136. {
  137. j++;
  138. p = p->next; //p指向下一个结点
  139. }
  140. if (!p->next || j > i - 1) //删除位置不合理
  141. {
  142. return -1;
  143. }
  144. q = p->next; //指向待删除的结点
  145. p->next = q->next; //
  146. *e = q->data;
  147. free(q);
  148. return 1;
  149. }
  150. //打印函数
  151. void Display(ElemType e)
  152. {
  153. printf("%c, ", e);
  154. }
  155. //将元素输出
  156. void ListTraverse(LinkList L, void(*visit)(ElemType))
  157. {
  158. LinkList p = L->next;
  159. while (p)
  160. {
  161. visit(p->data);
  162. p = p->next;
  163. }
  164. printf("\n");
  165. }
  166. //求和函数
  167. void ListAdd(LinkList &list1, LinkList &list2)
  168. {
  169. ElemType e; //用来暂时存放元素
  170. LinkList p1 = list1->next; //首先将指针赋值给变量p1和p2,使用指针来遍历链表
  171. LinkList p2 = list2->next;
  172. while (p1)
  173. {
  174. while (p2)
  175. {
  176. int pos = LocateElem(list1, p2->data, ListCompare); //寻找元素的位置
  177. if (pos) //如果元素存在,则将元素删除
  178. {
  179. ListDelete(list1, pos, &e); //删除元素
  180. }
  181. else
  182. {
  183. ListInsert(list1, 1, p2->data); //插入元素
  184. }
  185. p2 = p2->next; //移动指针,遍历链表
  186. }
  187. p1 = p1->next; //移动指针,遍历链表
  188. }
  189. }
  190. int main(void)
  191. {
  192. char A[] = { 'c', 'b', 'e', 'g', 'f', 'd'}; //初始化插入元素
  193. char B[] = { 'a', 'b', 'n', 'f'};
  194. LinkList list1; //用链表来保存数据
  195. LinkList list2;
  196. InitList(&list1); //初始化链表
  197. InitList(&list2);
  198. //初始化链表
  199. for (int i = 0; i < 6; i++)
  200. {
  201. ListInsert(list1, i + 1, A[i]); //将链表初始化
  202. }
  203. for (int i = 0; i < 4; i++)
  204. {
  205. ListInsert(list2, i + 1, B[i]); //将链表初始化
  206. }
  207. ListTraverse(list1, Display); //显示链表当前状态
  208. ListTraverse(list2, Display);
  209. ListAdd(list1, list2);
  210. //输出链表的结果
  211. ListTraverse(list1, Display); //显示结果
  212. ClearList(list1);
  213. ClearList(list2);
  214. system("pause"); //让程序等待
  215. return 0;
  216. }

运算结果:

在这里插入图片描述
链表遍历查找相同元素的算法效率还不是很高,如果你有更加好的方法欢迎给我留言。

发表评论

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

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

相关阅读

    相关 C语言】模拟实现

    链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)访问特定编号的节点

    相关 C语言实现

    链表和我们之前实现过的顺序表一样,都是简单的数据结构,链表分为单向链表、双向链表、循环链表。而单向链表又分为两种实现方法,一种为带头节点的单链表,一种为不带头节点的单链表。我们