当前位置:   article > 正文

数据结构——双向循环链表(C语言实现)_双向循环链表c语言代码

双向循环链表c语言代码

目录

双向循环链表:结构复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势

这是双向循环链表的示意图(注意第一个为哨兵卫头节点)

头文件及定义

  1. #pragma once
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <assert.h>
  5. typedef int LTDataType;
  6. typedef struct ListNode
  7. {
  8. LTDateType data;
  9. struct ListNode* next;
  10. struct ListNode* prev;
  11. }LTNode;
  12. LTNode* ListInit();//初始化
  13. void ListDestroy(LTNode* phead);//销毁
  14. void ListPrint(LTNode* phead);//打印
  15. LTNode* BuyListNode(LTDataType x);//创建新节点
  16. void ListPushBack(LTNode* phead, LTDataType x);//尾插
  17. void ListPopBack(LTNode* phead);//尾删
  18. void ListPushFront(LTNode* phead, LTDataType x);//头插
  19. void ListPopFront(LTNode* phead);//头删
  20. LTNode* ListFind(LTNode* phead, LTDataType x);//查找
  21. void ListInsert(LTNode* pos, LTDataType x);//在pos之前位置插入
  22. void ListErase(LTNode* pos);//删除pos元素

双链表初始化

头节点不存储有效数据,自己指向自己

  1. LTNode* ListInit()//采用返回指针的方式,不需要用二级指针了
  2. {
  3. // 哨兵位头结点(不存储有效数据)
  4. LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
  5. phead->next = phead;
  6. phead->prev = phead;
  7. return phead;
  8. }

双链表打印

  1. void ListPrint(LTNode* phead)
  2. {
  3. assert(phead);
  4. LTNode* cur = phead->next;
  5. while (cur != phead)
  6. {
  7. printf("%d ", cur->data);
  8. cur = cur->next;
  9. }
  10. printf("\n");
  11. }

双链表创建新节点

  1. LTNode* BuyListNode(LTDataType x)
  2. {
  3. LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
  4. newnode->data = x;
  5. newnode->next = NULL;
  6. newnode->prev = NULL;
  7. return newnode;
  8. }

双链表尾插

  1. void ListPushBack(LTNode* phead, LTDataType x)
  2. //不改变plist,改变的是plist指向的结构体,不需要二级指针了
  3. {
  4. assert(phead);//头节点不能为空,
  5. //这段注释为第一种方法
  6. //LTNode* tail = phead->prev;
  7. //LTNode* newnode = BuyListNode(x);
  8. //tail->next = newnode;
  9. //newnode->prev = tail;
  10. //newnode->next = phead;
  11. //phead->prev = newnode;
  12. ListInsert(phead, x);//第二种方法,复用插入接口
  13. }

双链表尾删

  1. void ListPopBack(LTNode* phead)
  2. {
  3. assert(phead);
  4. assert(phead->next != phead);
  5. 第一种方法
  6. //LTNode* tail = phead->prev;
  7. //phead->prev = tail->prev;
  8. //tail->prev->next = phead;
  9. //free(tail);
  10. ListErase(phead->prev);//复用
  11. }

双链表头插

  1. void ListPushFront(LTNode* phead, LTDataType x)
  2. {
  3. assert(phead);
  4. 第一种方法
  5. //LTNode* newnode = BuyListNode(x);
  6. //LTNode* next = phead->next;
  7. //phead->next = newnode;
  8. //newnode->prev = phead;
  9. //newnode->next = next;
  10. //next->prev = newnode;
  11. ListInsert(phead->next, x);//复用
  12. }

双链表头删

  1. void ListPopFront(LTNode* phead)
  2. {
  3. assert(phead);
  4. assert(phead->next != phead);// 链表空了就不删
  5. //第一种方法
  6. //LTNode* next = phead->next;
  7. //LTNode* nextNext = next->next;
  8. //phead->next = nextNext;
  9. //nextNext->prev = phead;
  10. //free(next);
  11. ListErase(phead->next);//复用
  12. }

双链表查找

  1. LTNode* ListFind(LTNode* phead, LTDataType x)
  2. {
  3. assert(phead);
  4. LTNode* cur = phead->next;
  5. while (cur != phead)
  6. {
  7. if (cur->data == x)
  8. {
  9. return cur;
  10. }
  11. cur = cur->next;
  12. }
  13. return NULL;//找不到返回NULL
  14. }

双链表删除元素

需要配合查找才能使用

  1. // 删除pos位置
  2. void ListErase(LTNode* pos)
  3. {
  4. assert(pos);
  5. LTNode* posPrev = pos->prev;
  6. LTNode* posNext = pos->next;
  7. posPrev->next = posNext;
  8. posNext->prev = posPrev;
  9. free(pos);
  10. pos = NULL;
  11. }

双链表在pos位置之前插入

  1. void ListInsert(LTNode* pos, LTDataType x)
  2. {
  3. assert(pos);
  4. LTNode* posPrev = pos->prev;
  5. LTNode* newnode = BuyListNode(x);
  6. posPrev->next = newnode;
  7. newnode->prev = posPrev;
  8. newnode->next = pos;
  9. pos->prev = newnode;
  10. }

双链表销毁

  1. void ListDestroy(LTNode* phead)
  2. {
  3. assert(phead);
  4. LTNode* cur = phead->next;
  5. while (cur != phead)
  6. {
  7. LTNode* next = cur->next;
  8. free(cur);
  9. cur = next;
  10. }
  11. free(phead);
  12. phead = NULL;//由于没传二级指针,需要在外面让plist = NULL才有用
  13. }

代码测试

  1. void TestList1()
  2. {
  3. LTNode* plist = ListInit();
  4. ListPushBack(plist, 1);
  5. ListPushBack(plist, 2);
  6. ListPushBack(plist, 3);
  7. ListPushBack(plist, 4);
  8. ListPushBack(plist, 5);
  9. ListPrint(plist);
  10. ListPopBack(plist);
  11. ListPopBack(plist);
  12. ListPopBack(plist);
  13. ListPopBack(plist);
  14. ListPrint(plist);
  15. }
  16. void TestList2()
  17. {
  18. LTNode* plist = ListInit();
  19. ListPushFront(plist, 1);
  20. ListPushFront(plist, 2);
  21. ListPushFront(plist, 3);
  22. ListPushFront(plist, 4);
  23. ListPrint(plist);
  24. ListPushBack(plist, 1);
  25. ListPushBack(plist, 2);
  26. ListPushBack(plist, 3);
  27. ListPushBack(plist, 4);
  28. ListPrint(plist);
  29. LTNode* pos1 = ListFind(plist, 2);
  30. if (pos1)
  31. {
  32. ListErase(pos1);
  33. }
  34. ListPrint(plist);
  35. ListPopBack(plist);
  36. ListPopBack(plist);
  37. ListPopFront(plist);
  38. ListPopFront(plist);
  39. ListPrint(plist);
  40. ListDestroy(plist);
  41. plist = NULL;
  42. }
  43. int main()
  44. {
  45. TestList1();
  46. TestList2();
  47. return 0;
  48. }

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

闽ICP备14008679号