【数据结构】双向链表

喜欢ヅ旅行 2022-05-16 09:46 380阅读 0赞

1.LinkedList.h

  1. #ifndef LINKED_LIST_H
  2. #define LINKED_LIST_H
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. //首先定义一个链表节点结构体
  7. typedef struct LINKNODE{
  8. void* data;//表示节点中存储任意类型的数据
  9. struct LINKNODE* pre;//注意这种定义的方式啊
  10. struct LINKNODE* next;//注意这种定义的方式啊,前面是struct 后面是LINKNODE是最开始定义的结构体名称,LinkNode是另外定义的名称
  11. }LinkNode;
  12. //再定义链表结构体
  13. typedef struct {
  14. //注意,下面的LinkNode可以不是指针就是LinkNode head,改成不是指针后可能还方便点,
  15. //如果head不是指针至少在初始化list的时候不用新开辟一片内存,同样也是作为头节点,
  16. //而不是数据存储的第一个点,读者可以自行尝试把下面的指针改为不是指针
  17. LinkNode* head;//给链表定义一个头
  18. int size;//记录当前list存储的元素数量
  19. }LinkList;
  20. //打印函数指针
  21. typedef void(*PRINTLINKNODE)(void*);
  22. //初始化链表
  23. LinkList* initLinkList();
  24. //指定位置插入
  25. void insertLinkList(LinkList* list, int pos, void* data);
  26. //删除指定位置的值
  27. void removeByPosLinkList(LinkList* list, int pos);
  28. //获得链表的长度
  29. int getLinkListSize(LinkList* list);
  30. //查找
  31. int findPosByData(LinkList* list, void* data);
  32. //返回第一个结点
  33. void* frontLinkList(LinkList* list);
  34. //返回最后一个结点
  35. void* backLinkList(LinkList* list);
  36. //打印链表结点
  37. void printLinkList(LinkList* list, PRINTLINKNODE print);
  38. //释放链表内存
  39. void freeSpaceLinkList(LinkList* list);
  40. //从后面加入
  41. void pushBack(LinkList* list, void* data);
  42. //从后面弹出
  43. void popBack(LinkList* list);
  44. //从前面加入
  45. void pushFront(LinkList* list, void* data);
  46. //从前面弹出
  47. void popFront(LinkList* list);
  48. #endif // !LINKED_LIST_H

2.LinkedList.c

  1. #include "LinkedList.h"
  2. //初始化链表
  3. LinkList* initLinkList() {
  4. LinkList* linkList = (LinkList*)malloc(sizeof(LinkList));
  5. //新建个数据节点,让list指向这个节点,这个节点作为list的头节点,不存储数据,只用next记录下真实的存储的第一个位置
  6. //这样做的目的是为了便于遍历
  7. linkList->head= (LinkNode*)malloc(sizeof(LinkNode));
  8. linkList->head->data = NULL;
  9. linkList->head->pre = NULL;
  10. linkList->head->next = NULL;
  11. linkList->size = 0;
  12. return linkList;
  13. }
  14. //指定位置插入
  15. void insertLinkList(LinkList* list, int pos, void* data) {
  16. if (list == NULL) {
  17. return;
  18. }
  19. if (data == NULL) {
  20. return;
  21. }
  22. if (pos < 0 || pos >= list->size) {
  23. pos = list->size;
  24. }
  25. //创建新的结点
  26. LinkNode* newNode = (LinkNode*)malloc(sizeof(LinkNode));
  27. newNode->data = data;
  28. newNode->next = NULL;
  29. //辅助指针
  30. LinkNode* pCurrent = list->head;
  31. for (int i = 0; i < pos; i++) {
  32. pCurrent = pCurrent->next;
  33. }
  34. //将新节点加入链表
  35. newNode->pre = pCurrent;
  36. newNode->next = pCurrent->next;
  37. pCurrent->next = newNode;
  38. list->size++;
  39. }
  40. //删除指定位置的值
  41. void removeByPosLinkList(LinkList* list, int pos) {
  42. if (list == NULL) {
  43. return;
  44. }
  45. if (pos < 0 || pos >= list->size) {
  46. return;
  47. }
  48. //辅助指针
  49. LinkNode* pCurrent = list->head;
  50. for (int i = 0; i < pos; i++) {
  51. pCurrent = pCurrent->next;
  52. }
  53. //缓存删除的节点
  54. LinkNode* pDel = pCurrent->next;
  55. pCurrent->next = pDel->next;
  56. //释放删除节点的内存
  57. free(pDel);
  58. list->size--;
  59. }
  60. //获得链表的长度
  61. int getLinkListSize(LinkList* list) {
  62. return list->size;
  63. }
  64. //查找
  65. int findPosByData(LinkList* list, void* data) {
  66. if (list == NULL) return -10086;
  67. if (data == NULL) return -10086;
  68. LinkNode* firstNode = list->head->next;
  69. int pos = 0;
  70. while (firstNode!= NULL) {
  71. if (firstNode->data == data) {
  72. return pos;
  73. }
  74. firstNode = firstNode->next;
  75. pos++;
  76. }
  77. return -10086;//表示没有找到
  78. }
  79. //返回第一个结点
  80. void* frontLinkList(LinkList* list) {
  81. if (list == NULL) return NULL;
  82. return list->head->next->data;
  83. }
  84. //返回最后一个结点
  85. void* backLinkList(LinkList* list) {
  86. if (list == NULL) return NULL;
  87. LinkNode* pCurrent = list->head;
  88. for (int i = 0; i < list->size; i++) {
  89. pCurrent = pCurrent->next;
  90. }
  91. return pCurrent->data;
  92. }
  93. //打印链表结点
  94. void printLinkList(LinkList* list, PRINTLINKNODE print) {
  95. if (list == NULL) return;
  96. //辅助指针变量
  97. LinkNode* pCurrent = list->head->next;
  98. while (pCurrent != NULL) {
  99. print(pCurrent->data);
  100. pCurrent = pCurrent->next;
  101. }
  102. }
  103. //释放链表内存
  104. void freeSpaceLinkList(LinkList* list){
  105. if (list == NULL) {
  106. return;
  107. }
  108. //辅助指针变量
  109. LinkNode* pCurrent = list->head;
  110. while (pCurrent != NULL) {
  111. //缓存下一个结点
  112. LinkNode* pNext = pCurrent->next;
  113. free(pCurrent);
  114. pCurrent = pNext;
  115. }
  116. //释放链表内存
  117. list->size = 0;
  118. free(list);
  119. }
  120. //从后面加入
  121. void pushBack(LinkList* list, void* data) {
  122. if (list == NULL) {
  123. return;
  124. }
  125. if (data == NULL) {
  126. return;
  127. }
  128. insertLinkList(list, list->size, data);
  129. }
  130. //从后面弹出
  131. void popBack(LinkList* list) {
  132. if (list == NULL) return;
  133. //获得最后一个指针
  134. LinkNode* pCurrent = list->head;
  135. while (pCurrent->next != NULL) {
  136. pCurrent = pCurrent->next;
  137. }
  138. //把最后一个的前一个的指针的next指向NULL
  139. pCurrent->pre->next = NULL;
  140. //释放掉最后一个指针
  141. free(pCurrent);
  142. list->size--;
  143. }
  144. //从前面加入
  145. void pushFront(LinkList* list, void* data) {
  146. if (list == NULL) {
  147. return;
  148. }
  149. if (data == NULL) {
  150. return;
  151. }
  152. insertLinkList(list, 0, data);
  153. }
  154. //从前面弹出
  155. void popFront(LinkList* list) {
  156. if (list == NULL) return;
  157. if (list->size == 0) return;
  158. //先保存第一个阶段的的指针
  159. LinkNode* firstNode = list->head->next;
  160. //再将头指针的下一个指针指向第一个的下一个
  161. list->head->next = firstNode->next;
  162. //再将第二个的pre设置为头指针
  163. firstNode->next->pre = list->head;
  164. //最后释放第一个指针
  165. free(firstNode);
  166. //size减小一个
  167. list->size--;
  168. }

3.测试

  1. #include "LinkedList.h"
  2. //自定义数据类型
  3. typedef struct PERSON {
  4. char name[64];
  5. int age;
  6. int score;
  7. }Person;
  8. //打印函数
  9. void MyPrint(void* data) {
  10. Person* p = (Person*)data;
  11. printf("Name:%s Age:%d Score:%d\n", p->name, p->age, p->score);
  12. }
  13. void test01() {
  14. LinkList* list = initLinkList();
  15. Person p1 = { "xiaodong",20,56 };
  16. Person p2 = { "xiaoxiao",30,78 };
  17. Person p3 = { "dogndong",20,22 };
  18. Person p4 = { "kankan",46,13 };
  19. Person p5 = { "hehe",62,34 };
  20. Person p6 = { "lishang",67,55 };
  21. printf("size:%d\n", getLinkListSize(list));
  22. pushBack(list, &p1);
  23. printf("size:%d\n", getLinkListSize(list));
  24. pushBack(list, &p2);
  25. pushBack(list, &p3);
  26. pushBack(list, &p4);
  27. pushBack(list, &p5);
  28. pushFront(list, &p6);
  29. printLinkList(list, MyPrint);
  30. printf("size:%d\n", getLinkListSize(list));
  31. printf("-----------从后面弹出----------\n");
  32. popBack(list);
  33. printLinkList(list, MyPrint);
  34. printf("size:%d\n", getLinkListSize(list));
  35. printf("-----------从前面弹出----------\n");
  36. popFront(list);
  37. printLinkList(list, MyPrint);
  38. printf("size:%d\n", getLinkListSize(list));
  39. printf("-----------返回第一个节点数据----------\n");
  40. MyPrint(frontLinkList(list));
  41. printf("-----------返回最后一个节点数据----------\n");
  42. MyPrint(backLinkList(list));
  43. }
  44. int main(void) {
  45. test01();
  46. system("pause");
  47. return 0;
  48. }

发表评论

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

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

相关阅读

    相关 数据结构双向

    > 前面我们已经学完了单向链表,知道了单向链表如何进行增删查改等基本功能,而今天,我们将要学习双向链表。 目录 1.链表的分类 2.双向链表定义 3.双向链表接口的实现

    相关 数据结构 双向

    做一个豁达而努力的自己。 双向链表的定义:在单链表的每个节点中,再设置一个指向其前驱节点的指针域。 线性表的双向链表的存储结构: typedef struct DulNo