• 带头双向循环链表


    目录

    一、结构定义

    二、结点创建

    三、头结点初始化

    四、链表打印 

    五、尾插

    六、头插

    七、尾删

    八、头删

    九、查找(返回结点)

    十、任意位置插入

    十一、任意位置删除

    十二、利用LTInsert写尾插函数

    十三、利用LTInsert写头插函数

    十四、利用LTErase写尾删函数

    十五、利用LTErase写头删函数

    十六、销毁链表 

    十七、测试代码


    一、结构定义

    1. //带头双向循环链表的结构定义
    2. typedef int LTDataType;
    3. typedef struct ListNode {
    4. LTDataType val;
    5. struct LTNode* next;
    6. struct LTNode* prev;
    7. }LTNode;

    二、结点创建

    1. //带头双向循环链表结点创建
    2. LTNode* CreateLTNode(LTDataType x)
    3. {
    4. LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
    5. if (newnode == NULL)
    6. {
    7. perror("malLoc fail:");
    8. exit(-1);
    9. }
    10. newnode->val = x;
    11. newnode->next = NULL;
    12. newnode->prev = NULL;
    13. return newnode;
    14. }

    三、头结点初始化

    1. //带头双向循环链表的初始化
    2. LTNode* LTInit(LTNode* phead)
    3. {
    4. phead = CreateLTNode(-1);
    5. phead->next = phead;
    6. phead->prev = phead;
    7. return phead;
    8. }

    四、链表打印 

    1. //带头双向循环链表的打印
    2. void LTPrint(LTNode* phead)
    3. {
    4. assert(phead);
    5. LTNode* cur = phead->next;
    6. while (cur != phead)
    7. {
    8. printf("%d<=>", cur->val);
    9. cur = cur->next;
    10. }
    11. printf("\n");
    12. }

    五、尾插

    1. //带头双向循环链表的尾插
    2. void LTPushBack(LTNode* phead, LTDataType x)
    3. {
    4. assert(phead);
    5. LTNode* newnode = CreateLTNode(x);
    6. LTNode* tail = phead->prev;//尾指针
    7. //尾插
    8. tail->next = newnode;
    9. newnode->prev = tail;
    10. newnode->next = phead;
    11. phead->prev = newnode;
    12. }

    六、头插

    1. //带头双向循环链表的头插
    2. void LTPushFront(LTNode* phead, LTDataType x)
    3. {
    4. assert(phead);
    5. LTNode* newnode = CreateLTNode(x);
    6. LTNode* first = phead->next;
    7. newnode->next = first;
    8. first->prev = newnode;
    9. phead->next = newnode;
    10. newnode->prev = phead;
    11. }

    七、尾删

    1. //带头双向循环链表的尾删
    2. void LTPopBack(LTNode* phead)
    3. {
    4. assert(phead);
    5. assert(phead->next != phead);//空链表不能删
    6. LTNode* tail1 = phead->prev;//尾1结点
    7. LTNode* tail2 = tail1->prev;//尾2结点
    8. tail2->next = phead;
    9. phead->prev = tail2;
    10. free(tail1);
    11. tail1 = NULL;
    12. }

    八、头删

    1. //带头双向循环链表的头删
    2. void LTPopFront(LTNode* phead)
    3. {
    4. assert(phead);
    5. assert(phead->next != phead);//空链表不能删
    6. LTNode* first = phead->next;
    7. LTNode* second = first->next;
    8. free(first);
    9. first = NULL;
    10. phead->next = second;
    11. second->prev = phead;
    12. }

    九、查找(返回结点)

    1. //带头双向循环链表的查找
    2. LTNode* LTFind(LTNode* phead, LTDataType x)
    3. {
    4. assert(phead);
    5. LTNode* cur = phead->next;
    6. while (cur != phead)
    7. {
    8. if (cur->val == x)
    9. return cur;
    10. else
    11. cur = cur->next;
    12. }
    13. return NULL;
    14. }

    十、任意位置插入

    如果插入位置是哨兵位,那么相当于尾插

    如果插入位置是哨兵位的后一结点,那么相当于头插

    1. //带头双向循环链表的任意位置插入
    2. void LTInsert(LTNode* pos, LTDataType x)
    3. {
    4. assert(pos);//插入位置必须有效
    5. LTNode* newnode = CreateLTNode(x);
    6. LTNode* posPrev = pos->prev;
    7. newnode->next = pos;
    8. pos->prev = newnode;
    9. posPrev->next = newnode;
    10. newnode->prev = posPrev;
    11. }

    十一、任意位置删除

    如果删除位置是哨兵位的后一结点,那么相当于头删

    如果删除位置是哨兵位的前一结点,那么相当于尾删

    1. //带头双向循环链表的任意位置删除
    2. void LTErase(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. }

    十二、利用LTInsert写尾插函数

    1. //利用LTInsert写尾插函数
    2. void LTPushBackInsert(LTNode* phead, LTDataType x)
    3. {
    4. assert(phead);
    5. LTInsert(phead, x);
    6. }

    十三、利用LTInsert写头插函数

    1. //利用LTInsert写头插函数
    2. void LTPushFrontInsert(LTNode* phead, LTDataType x)
    3. {
    4. assert(phead);
    5. LTInsert(phead->next, x);
    6. }

    十四、利用LTErase写尾删函数

    1. //利用LTErase写尾删函数
    2. void LTPopBackErase(LTNode* phead)
    3. {
    4. assert(phead->next != phead);//链表为空不能删除
    5. LTErase(phead->prev);
    6. }

    十五、利用LTErase写头删函数

    1. //利用LTErase写头删函数
    2. void LTPopFrontErase(LTNode* phead)
    3. {
    4. assert(phead->next != phead);
    5. LTErase(phead->next);
    6. }

    十六、销毁链表 

    1. //销毁带头双向循环链表
    2. void LTDestroy(LTNode* phead)
    3. {
    4. assert(phead);
    5. LTNode* cur = phead->next;
    6. while (cur != phead)
    7. {
    8. LTNode* tmp = cur;
    9. cur = cur->next;
    10. free(tmp);
    11. }
    12. free(phead);
    13. }

    十七、测试代码

    1. void test01()
    2. {
    3. //初始化哨兵位
    4. LTNode* plist = NULL;
    5. plist = LTInit(plist);
    6. //LTNode* plist = LTInit(plist);
    7. //尾插
    8. LTPushBack(plist, 1);
    9. LTPushBack(plist, 2);
    10. LTPushBack(plist, 3);
    11. LTPushBack(plist, 4);
    12. LTPushBack(plist, 5);
    13. LTPushBack(plist, 6);
    14. //头插
    15. LTPushFront(plist, 1);
    16. LTPushFront(plist, 2);
    17. LTPushFront(plist, 3);
    18. LTPushFront(plist, 4);
    19. LTPushFront(plist, 5);
    20. LTPushFront(plist, 6);
    21. //打印
    22. LTPrint(plist);
    23. //尾删
    24. LTPopBack(plist);
    25. LTPopBack(plist);
    26. LTPopBack(plist);
    27. //打印
    28. LTPrint(plist);
    29. //头删
    30. LTPopFront(plist);
    31. LTPopFront(plist);
    32. LTPopFront(plist);
    33. //打印
    34. LTPrint(plist);
    35. //查找值为2的结点并在该位置插入值为10的结点
    36. LTNode* pos1 = LTFind(plist, 2);
    37. LTInsert(pos1, 10);
    38. //打印
    39. LTPrint(plist);
    40. //查找值为3的结点并删除该结点
    41. LTNode* pos2 = LTFind(plist, 3);
    42. LTErase(pos2);
    43. //打印
    44. LTPrint(plist);
    45. //尾插
    46. LTPushBackInsert(plist, 1);
    47. LTPushBackInsert(plist, 2);
    48. LTPushBackInsert(plist, 3);
    49. LTPushBackInsert(plist, 4);
    50. //打印
    51. LTPrint(plist);
    52. //头插
    53. LTPushFrontInsert(plist, 1);
    54. LTPushFrontInsert(plist, 2);
    55. LTPushFrontInsert(plist, 3);
    56. LTPushFrontInsert(plist, 4);
    57. //打印
    58. LTPrint(plist);
    59. //尾删
    60. LTPopBackErase(plist);
    61. LTPopBackErase(plist);
    62. LTPopBackErase(plist);
    63. //打印
    64. LTPrint(plist);
    65. //头删
    66. LTPopFrontErase(plist);
    67. LTPopFrontErase(plist);
    68. LTPopFrontErase(plist);
    69. //打印
    70. LTPrint(plist);
    71. //销毁链表
    72. //LTDestroy(plist);
    73. //plist=NULL;
    74. }
    75. int main()
    76. {
    77. test01();
    78. return 0;
    79. }

     

  • 相关阅读:
    基于python的毕业设计的药店|药房管理系统
    剑指 Offer II 036. 后缀表达式
    【csapp lab】lab2_bomblab
    bp神经网络反向传播原理,BP神经网络反向传播
    3dmax中格式批量互转obj批量转fbx等等
    Linux----Ubuntu系统官网下载iso镜像文件
    【Linux】快速配置云服务器(学习用)
    vue实现文件上传压缩优化处理
    【ML02】Cost Function 损失函数
    HTML5 SVG
  • 原文地址:https://blog.csdn.net/2301_76197086/article/details/134383742