当前位置:   article > 正文

双链表的增删查改实现(c语言描述)_c语言双链表的增删改查题目

c语言双链表的增删改查题目

内容导读


1.什么是双链表

1.1 双链表概述

1.2循环链表

1.3 双链表的优点

2.双链表的定义以及常见功能的实现

2.0双链表定义以及常见功能头文件

2.1双链表定义(声明)

2.2双链表内存申请及扩容

2.3双链表初始化

2.4双链表的打印

2.5双链表的插入与删除操作理论

 2.6双链表头插操作代码实现

2.7双链表尾插操作代码实现

 2.8双链表的位置pos(已知)前插入操作代码实现

2.9双链表的头删操作代码实现

2.10双链表尾删操作代码实现

 2.11双链表的位置pos(已知)删除操作代码实现

 2.12双链表的元素查找,若找到目的值i则返回其地址pos,否则返回NULL

2.13双链表的元素查找修改,若找到目的值i则将i修改成e,并返回其地址,否则返回NULL

终:代码合集


1.什么是双链表

1.1 双链表概述

在线性表的链式存储结构中,每个物理结点增加一个指向后继结点的指针域(后指针)和一个指向前驱结点的指针域(前指针) ->双链表

 举个栗子:带头结点双链表结构

1.2循环链表

循环链表是另一种形式的链式存储结构形式。 

所以说双链表的形式就会有多种啦,比如循环双链表,带头结点的双链表,带头结点的循环双链表,带头结点的双链表等等。不过本质都是一样的,只需要学会任意一种,其他的只要注意一些不同的细节也能轻松实现。

1.3 双链表的优点

  • 从任一结点出发可以快速找到其前驱结点和后继结点;
  • 从任一结点出发可以访问其他结点。

双链表相比于单链表来说,双链表能够从任何一个结点访问其他任意结点,而单链表只能单方向访问下一个结点。虽然双链表的结构较比与单链表要复杂,但是双链表的操作要相比于单链表简单。

在本文中,双链表所有实现方式以带头结点的循环双链表为基础实现。

2.双链表的定义以及常见功能的实现

2.0双链表定义以及常见功能头文件

  1. #pragma once
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <assert.h>
  5. typedef int ListType;
  6. typedef struct ListNode //声明双链表结点结构
  7. {
  8. ListType data; //存储数据:data
  9. struct ListNode* prev; //指向前驱结点:前指针
  10. struct ListNode* next; //指向后继结点:后指针
  11. }ListNode;
  12. //实现双链表增删查改接口
  13. //双链表的初始化
  14. ListNode* ListInit();
  15. //双链表的打印
  16. void ListPrint(ListNode* phead);
  17. //双链表的头插
  18. void ListPushFront(ListNode* phead,ListType x);
  19. //双链表的头删
  20. void ListPopFront(ListNode* phead);
  21. //双链表的尾插
  22. void ListPushBack(ListNode* phead, ListType x);
  23. //双链表的尾删
  24. void ListPopBack(ListNode* phead);
  25. //双链表结点的扩容
  26. ListNode* BuyListNode(ListType x);
  27. //双链表的位置pos(已知)前插入
  28. void ListInsert( ListNode* pos, ListType x);
  29. //双链表的位置pos(已知)删除
  30. void ListErase( ListNode* pos);
  31. //双链表的元素查找,若找到目的值i则返回其地址pos,否则返回NULL
  32. ListNode* ListFind(ListNode* phead, ListType i);
  33. //双链表的元素查找修改,若找到目的值i则将i修改成e,并返回其地址,否则返回NULL
  34. ListNode* ListReplace(ListNode* phead, ListType i, ListType e);

2.1双链表定义(声明)

对于双链表,采用类似于单链表的类型定义,其结点类型ListNode声明如下:

  1. typedef int ListType;
  2. typedef struct ListNode //声明双链表结点结构
  3. {
  4. ListType data; //存储数据:data
  5. struct ListNode* prev; //指向前驱结点:前指针
  6. struct ListNode* next; //指向后继结点:后指针
  7. }ListNode;

2.2双链表内存申请及扩容

  1. //双链表结点申请及扩容
  2. ListNode* BuyListNode(ListType x)
  3. {
  4. ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); //新结点内存申请
  5. if (newNode == NULL) {
  6. printf("申请内存失败!");
  7. return NULL;
  8. }
  9. newNode->next = NULL;
  10. newNode->prev = NULL;
  11. newNode->data = x;
  12. return newNode; //将新申请的结点的前后指针置空,存入数据,返回新结点的地址
  13. }

2.3双链表初始化

  1. //双链表的初始化
  2. ListNode* ListInit()
  3. {
  4. ListNode* phead = BuyListNode(0); //申请新结点作为头指针
  5. phead->next = phead; //初始化的双链表前后指针均指向本身
  6. phead->prev = phead;
  7. return phead; //返回指针地址
  8. }

2.4双链表的打印

需要打印双链表中的每个数据,就需要遍历整个双链表,需要遍历双链表,那就要找到遍历双链表的条件,由于我是以带头结点的循环双链表为基础,那么遍历终结的条件不是指向NULL,而是指向头结点地址,因为当遍历完一次后,指针就会指向初始结点。

  1. //双链表的打印
  2. void ListPrint(ListNode* phead)
  3. {
  4. assert(phead); //判断传入的地址是否为空,为空强制结束程序
  5. ListNode* cur = phead->next;
  6. while (cur!=phead)
  7. {
  8. printf("%d ", cur->data);
  9. cur = cur->next;
  10. }
  11. printf("\n");
  12. }

2.5双链表的插入与删除操作理论

双链表插入操作

 双链表删除操作

 2.6双链表头插操作代码实现

 双链表的头插相当于在第一个数据前插入

  1. //双链表的头插
  2. void ListPushFront(ListNode* phead, ListType x)
  3. {
  4. assert(phead);
  5. ListNode* newNode = BuyListNode(x);
  6. ListNode* next = phead->next; //保存第一个数据地址
  7. phead->next = newNode;
  8. newNode->prev = phead;
  9. next->prev = newNode;
  10. newNode->next = next;
  11. }

2.7双链表尾插操作代码实现

双链表的尾插相当于在头结点前插入

  1. //双链表的尾插
  2. void ListPushBack(ListNode* phead, ListType x)
  3. {
  4. assert(phead);
  5. ListNode* newNode = BuyListNode(x);
  6. ListNode* tail = phead->prev; //保存最后一个数据地址
  7. phead->prev = newNode;
  8. newNode->next = phead;
  9. tail->next = newNode;
  10. newNode->prev = tail;
  11. }

 2.8双链表的位置pos(已知)前插入操作代码实现

  1. //双链表的位置pos(已知)前插入
  2. void ListInsert(ListNode* pos, ListType x)
  3. {
  4. assert(pos);
  5. ListNode* newNode= BuyListNode(x);
  6. ListNode* posPrev = pos->prev;
  7. pos->prev = newNode;
  8. newNode->next = pos;
  9. posPrev->next = newNode;
  10. newNode->prev = posPrev;
  11. }

2.9双链表的头删操作代码实现

双链表头删相当于删除第一个数据 

  1. //双链表的头删
  2. void ListPopFront(ListNode* phead)
  3. {
  4. assert(phead);
  5. assert(phead->next != NULL);
  6. ListNode* first = phead->next;
  7. ListNode* second = first->next;
  8. phead->next = second;
  9. second->prev = phead;
  10. free(first);
  11. }

2.10双链表尾删操作代码实现

双链表尾删相当于删除最后一个数据

  1. //双链表的尾删
  2. void ListPopBack(ListNode* phead)
  3. {
  4. assert(phead);
  5. assert(phead->next != NULL);
  6. ListNode* tail = phead->prev;
  7. ListNode* tailPrev = tail->prev;
  8. phead->prev = tailPrev;
  9. tailPrev->next = phead;
  10. free(tail);
  11. }

 2.11双链表的位置pos(已知)删除操作代码实现

  1. //双链表的位置pos(已知)删除
  2. void ListErase( ListNode* pos)
  3. {
  4. assert(pos);
  5. ListNode* posPrev = pos->prev;
  6. ListNode* posNext = pos->next;
  7. posPrev->next = posNext;
  8. posNext->prev = posPrev;
  9. }

 2.12双链表的元素查找,若找到目的值i则返回其地址pos,否则返回NULL

  1. //双链表的元素查找,若找到目的值i则返回其地址pos,否则返回NULL
  2. ListNode* ListFind(ListNode* phead, ListType i)
  3. {
  4. assert(phead);
  5. ListNode* cur = phead->next;
  6. while (cur != phead) {
  7. if (cur->data == i)
  8. return cur;
  9. cur = cur->next;
  10. }
  11. return NULL;
  12. }

2.13双链表的元素查找修改,若找到目的值i则将i修改成e,并返回其地址,否则返回NULL

  1. //双链表的元素查找修改,若找到目的值i则将i修改成e,并返回其地址,否则返回NULL
  2. ListNode* ListReplace(ListNode* phead, ListType i, ListType e)
  3. {
  4. assert(phead);
  5. ListNode* cur = phead->next;
  6. while (cur != phead) {
  7. if (cur->data == i)
  8. {
  9. cur->data = e;
  10. return cur;
  11. }
  12. cur = cur->next;
  13. }
  14. return NULL;
  15. }

终:代码合集

  1. #include "List.h"
  2. //双链表的初始化
  3. ListNode* ListInit()
  4. {
  5. ListNode* phead = BuyListNode(0);
  6. phead->next = phead;
  7. phead->prev = phead;
  8. return phead;
  9. }
  10. //双链表的打印
  11. void ListPrint(ListNode* phead)
  12. {
  13. assert(phead);
  14. ListNode* cur = phead->next;
  15. while (cur!=phead)
  16. {
  17. printf("%d ", cur->data);
  18. cur = cur->next;
  19. }
  20. printf("\n");
  21. }
  22. //双链表的头插
  23. void ListPushFront(ListNode* phead, ListType x)
  24. {
  25. assert(phead);
  26. ListNode* newNode = BuyListNode(x);
  27. ListNode* next = phead->next;
  28. phead->next = newNode;
  29. newNode->prev = phead;
  30. next->prev = newNode;
  31. newNode->next = next;
  32. }
  33. //双链表的头删
  34. void ListPopFront(ListNode* phead)
  35. {
  36. assert(phead);
  37. assert(phead->next != NULL);
  38. ListNode* first = phead->next;
  39. ListNode* second = first->next;
  40. phead->next = second;
  41. second->prev = phead;
  42. free(first);
  43. }
  44. //双链表的尾插
  45. void ListPushBack(ListNode* phead, ListType x)
  46. {
  47. assert(phead);
  48. ListNode* newNode = BuyListNode(x);
  49. ListNode* tail = phead->prev;
  50. phead->prev = newNode;
  51. newNode->next = phead;
  52. tail->next = newNode;
  53. newNode->prev = tail;
  54. }
  55. //双链表的尾删
  56. void ListPopBack(ListNode* phead)
  57. {
  58. assert(phead);
  59. assert(phead->next != NULL);
  60. ListNode* tail = phead->prev;
  61. ListNode* tailPrev = tail->prev;
  62. phead->prev = tailPrev;
  63. tailPrev->next = phead;
  64. free(tail);
  65. }
  66. //双链表结点的扩容
  67. ListNode* BuyListNode(ListType x)
  68. {
  69. ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
  70. if (newNode == NULL) {
  71. printf("申请内存失败!");
  72. return NULL;
  73. }
  74. newNode->next = NULL;
  75. newNode->prev = NULL;
  76. newNode->data = x;
  77. return newNode;
  78. }
  79. //双链表的位置pos(已知)前插入
  80. void ListInsert(ListNode* pos, ListType x)
  81. {
  82. assert(pos);
  83. ListNode* newNode= BuyListNode(x);
  84. ListNode* posPrev = pos->prev;
  85. pos->prev = newNode;
  86. newNode->next = pos;
  87. posPrev->next = newNode;
  88. newNode->prev = posPrev;
  89. }
  90. //双链表的位置pos(已知)删除
  91. void ListErase( ListNode* pos)
  92. {
  93. assert(pos);
  94. ListNode* posPrev = pos->prev;
  95. ListNode* posNext = pos->next;
  96. posPrev->next = posNext;
  97. posNext->prev = posPrev;
  98. }
  99. //双链表的元素查找,若找到目的值i则返回其地址pos,否则返回NULL
  100. ListNode* ListFind(ListNode* phead, ListType i)
  101. {
  102. assert(phead);
  103. ListNode* cur = phead->next;
  104. while (cur != phead) {
  105. if (cur->data == i)
  106. return cur;
  107. cur = cur->next;
  108. }
  109. return NULL;
  110. }
  111. //双链表的元素查找修改,若找到目的值i则将i修改成e,并返回其地址,否则返回NULL
  112. ListNode* ListReplace(ListNode* phead, ListType i, ListType e)
  113. {
  114. assert(phead);
  115. ListNode* cur = phead->next;
  116. while (cur != phead) {
  117. if (cur->data == i)
  118. {
  119. cur->data = e;
  120. return cur;
  121. }
  122. cur = cur->next;
  123. }
  124. return NULL;
  125. }

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

闽ICP备14008679号