双向循环链表的接口

打印 上一主题 下一主题

主题 909|帖子 909|积分 2727

双向循环链表的接口

头文件
  1. #include <stdbool.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. ​```
复制代码
创建链表、节点
  1. // 指的是双向循环链表中的结点有效数据类型,用户可以根据需要进行修改hj
  2. typedef int DataType_t;
  3. // 构造双向循环链表的结点,链表中所有结点的数据类型应该是相同的
  4. typedef struct DoubleCircLinkedList
  5. {
  6.         DataType_t data;                                   // 结点的数据域
  7.         struct DoubleCircLinkedList *prev; // 直接前驱的指针域
  8.         struct DoubleCircLinkedList *next; // 直接后继的指针域
  9. } DoubleCircLList_t;
  10. /********************************************************************
  11. *
  12. *        name         :        DoubleCircLList_HeadInsert
  13. *        function :  创建一个空双向循环链表,空链表应该有一个头结点,对链表进行初始化
  14. *        argument :
  15. *                                @data:节点需存储的数据
  16. *        retval         :  返回新创建链表头节点的地址
  17. *        author         :  17647576169@163.com
  18. *        date         :  2024-4-24
  19. *         note         :        None
  20. *
  21. * *****************************************************************/
  22. DoubleCircLList_t *DoubleCircCirLList_Create(void)
  23. {
  24.         // 1.创建一个头结点并对头结点申请内存
  25.         DoubleCircLList_t *Head = (DoubleCircLList_t *)calloc(1, sizeof(DoubleCircLList_t));
  26.         if (NULL == Head)
  27.         {
  28.                 perror("Calloc memory for Head is Failed");
  29.                 exit(-1);
  30.         }
  31.         // 2.对头结点进行初始化,头结点是不存储数据域,指针域指向自身即可,体现“循环”
  32.         Head->prev = Head;
  33.         Head->next = Head;
  34.         // 3.把头结点的地址返回即可
  35.         return Head;
  36. }
  37. /********************************************************************
  38. *
  39. *        name         :        DoubleCircLList_HeadInsert
  40. *        function :  创建新的结点,并对新结点进行初始化(数据域 + 指针域)
  41. *        argument :
  42. *                                @data:节点需存储的数据
  43. *        retval         :  返回新创建节点的地址
  44. *        author         :  17647576169@163.com
  45. *        date         :  2024-4-24
  46. *         note         :        None
  47. *
  48. * *****************************************************************/
  49. DoubleCircLList_t *DoubleCircCirLList_NewNode(DataType_t data)
  50. {
  51.         // 1.创建一个新结点并对新结点申请内存
  52.         DoubleCircLList_t *New = (DoubleCircLList_t *)calloc(1, sizeof(DoubleCircLList_t));
  53.         if (NULL == New)
  54.         {
  55.                 perror("Calloc memory for NewNode is Failed");
  56.                 return NULL;
  57.         }
  58.         // 2.对新结点的数据域和指针域(2个)进行初始化,指针域指向结点自身,体现“循环”
  59.         New->data = data;
  60.         New->prev = New;
  61.         New->next = New;
  62.         return New;
  63. }
  64. ​```
复制代码
三种插入方式

在链表的头部插入
  1. /********************************************************************
  2. *
  3. *        name         :        DoubleCircLList_HeadInsert
  4. *        function :  向链表的头部进行数据插入
  5. *        argument :        @head:目标链表
  6. *                                @data:需插入的数据
  7. *        retval         :  返回新创建链表节点的地址
  8. *        author         :  17647576169@163.com
  9. *        date         :  2024-4-24
  10. *         note         :        None
  11. *
  12. * *****************************************************************/
  13. bool DoubleCircLList_HeadInsert(DoubleCircLList_t *Head, DataType_t data)
  14. {
  15.         // 备份头节点
  16.         DoubleCircLList_t *Phead = Head;
  17.         // 1.创建新的结点,并对新结点进行初始化
  18.         DoubleCircLList_t *New = DoubleCircCirLList_NewNode(data);
  19.         if (NULL == New)
  20.         {
  21.                 printf("can not insert new node\n");
  22.                 return false;
  23.         }
  24.         // 2.判断链表是否为空,如果为空,则直接插入即可
  25.         if (Head == Head->next)
  26.         {
  27.                 Head->next = New;
  28.                 return true;
  29.         }
  30.         // 3.如果链表为非空,则把新结点插入到链表的头部
  31.         Phead->next->prev->next = New; // 尾结点指向新的首节点
  32.         New->prev = Phead->next->prev; // 新节点指向尾结点
  33.         New->next = Phead->next;           // 新节点指向原来的首节点
  34.         Phead->next->prev = New;           // 原首节点指向新节点
  35.         Head->next = New;                           // 头结点指向新节点
  36.         return true;
  37. }
  38. ​```
复制代码
在链表的尾部插入
  1. /********************************************************************
  2. *
  3. *        name         :        DoubleCircLList_TailInsert
  4. *        function :  向链表的尾部进行数据插入
  5. *        argument :        @head:目标链表
  6. *                                @data:需插入的数据
  7. *        retval         :  返回1成功0失败
  8. *        author         :  17647576169@163.com
  9. *        date         :  2024-4-24
  10. *         note         :        None
  11. *
  12. * *****************************************************************/
  13. bool DoubleCircLList_TailInsert(DoubleCircLList_t *Head, DataType_t data)
  14. {
  15.         // 备份首节点
  16.         DoubleCircLList_t *Phead = Head->next;
  17.         // 1.创建新的结点,并对新结点进行初始化
  18.         DoubleCircLList_t *New = DoubleCircCirLList_NewNode(data);
  19.         if (NULL == New)
  20.         {
  21.                 printf("can not insert new node\n");
  22.                 return false;
  23.         }
  24.         // 2.判断链表是否为空,如果为空,则直接插入即可
  25.         if (Head == Head->next)
  26.         {
  27.                 Head->next = New;
  28.                 return true;
  29.         }
  30.         // 3.如果链表为非空,则把新结点插入到链表的尾部
  31.         Phead->prev->next = New; // 尾结点指向新节点
  32.         New->prev = Phead->prev; // 新节点指向尾结点
  33.         New->next = Head->next;         // 新节点指向首节点
  34.         Phead->prev = New;                 // 首节点指向新节点
  35.         return true;
  36. }
  37. ​```
复制代码
在链表指定数据节点后插入
  1. /********************************************************************
  2. *
  3. *        name         :        DoubleCircLList_DestInsert
  4. *        function :  向链表的指定节点数据的节点后进行插入
  5. *        argument :        @head:目标链表
  6. *                                @data:需插入的数据
  7. *                                @dest:插入位置
  8. *        retval         :  返回1成功0失败
  9. *        author         :  17647576169@163.com
  10. *        date         :  2024-4-24
  11. *         note         :        None
  12. *
  13. * *****************************************************************/
  14. bool DoubleCircLList_DestInsert(DoubleCircLList_t *Head, DataType_t destval, DataType_t data)
  15. {
  16.         // 备份头节点
  17.         DoubleCircLList_t *Phead = Head;
  18.         // 备份首节点
  19.         DoubleCircLList_t *Temp = Head->next;
  20.         // 1.创建新的结点,并对新结点进行初始化
  21.         DoubleCircLList_t *New = DoubleCircCirLList_NewNode(data);
  22.         if (NULL == New)
  23.         {
  24.                 printf("can not insert new node\n");
  25.                 return false;
  26.         }
  27.         // 目标数据在头部
  28.         if (destval == Phead->next->data)
  29.         {
  30.                 DoubleCircLList_HeadInsert(Head, data);
  31.                 return true;
  32.         }
  33.         // 找目标数据
  34.         DoubleCircLList_t *P = NULL; // 定义变量保存找的目标数据的节点地址
  35.         while (Head->next != Temp->next)
  36.         {
  37.                 Temp = Temp->next;
  38.                 if (destval == Temp->data)
  39.                 {
  40.                         P = Temp;
  41.                         break;
  42.                 }
  43.         }
  44.         // 找不到目标数据
  45.         if (NULL == P)
  46.         {
  47.                 perror("The target data cannot be found\n");
  48.                 return false;
  49.         }
  50.         // 目标数据在尾部
  51.         if (Head->next == P->next)
  52.         {
  53.                 DoubleCircLList_TailInsert(Head, data);
  54.         }
  55.         // 节点在中间开始插入
  56.         else
  57.         {
  58.                 P->next->prev = New; // 目标节点的后继指向新节点
  59.                 New->next = P->next; // 新节点指向目标节点的后继
  60.                 P->next = New;                 // 目标节点指向新节点
  61.                 New->prev = P;                 // 新节点指向目标节点
  62.         }
  63.         return true;
  64. }
  65. ​```
复制代码
三种删除方式

删除链表头部的节点
  1. /********************************************************************
  2. *
  3. *        name         :        DoubleCircLList_HeadDel
  4. *        function :  头删
  5. *        argument :        @head:目标链表
  6. *
  7. *        retval         :  返回1成功0失败
  8. *        author         :  17647576169@163.com
  9. *        date         :  2024-4-24
  10. *         note         :        None
  11. *
  12. * *****************************************************************/
  13. bool DoubleCircLList_HeadDel(DoubleCircLList_t *Head)
  14. {
  15.         // 备份首节点地址
  16.         DoubleCircLList_t *Phead = Head;
  17.         // 备份头节点地址
  18.         DoubleCircLList_t *Temp = Head->next;
  19.         // 1.判断链表是否为空,如果为空
  20.         if (Head == Head->next)
  21.         {
  22.                 perror("Linked lists have no data\n");
  23.                 return false;
  24.         }
  25.         // 链表只有一首个节点
  26.         if (Head->next == Head->next->next)
  27.         {
  28.                 Temp->next = NULL; // 释放尾指针
  29.                 Temp->prev = NULL; // 释放首指针
  30.                 Head->next = Head; // 头指针重新指向
  31.                 free(Temp);                   // 释放堆内存
  32.         }
  33.         // 删除原首节点
  34.         else
  35.         {
  36.                 Temp->prev->next = Temp->next; // 尾结点指向二节点
  37.                 Temp->next->prev = Temp->prev; // 二节点指向尾节点
  38.                 Head->next = Head->next->next; // 头节点指向二节点
  39.                 Temp->next = NULL;                           // 原首节点尾指针释放
  40.                 Temp->prev = NULL;                           // 原首节点首指针释放
  41.                 free(Temp);
  42.         }
  43.         return true;
  44. }
  45. ​```
复制代码
删除链表尾部的节点
  1. /********************************************************************
  2. *
  3. *        name         :        DoubleCircLList_TailDel
  4. *        function :  尾删
  5. *        argument :        @head:目标链表
  6. *                                @data:需删除的数据
  7. *
  8. *        retval         :  返回1成功0失败
  9. *        author         :  17647576169@163.com
  10. *        date         :  2024-4-24
  11. *         note         :        None
  12. *
  13. * *****************************************************************/
  14. bool DoubleCircLList_TailDel(DoubleCircLList_t *Head)
  15. {
  16.         // 备份首节点地址
  17.         DoubleCircLList_t *Phead = Head->next;
  18.         // 备份尾节点地址
  19.         DoubleCircLList_t *Tail = Head->next->prev;
  20.         // 1.判断链表是否为空,如果为空
  21.         if (Head == Head->next)
  22.         {
  23.                 perror("Linked lists have no data\n");
  24.                 return false;
  25.         }
  26.         // 链表只有一首个节点
  27.         if (Head->next == Head->next->next)
  28.         {
  29.                 Phead->next = NULL; // 释放尾指针
  30.                 Phead->prev = NULL; // 释放首指针
  31.                 Phead = Head;                // 头指针重新指向
  32.                 free(Phead);                // 释放堆内存
  33.         }
  34.         // 删除链表尾部节点
  35.         Tail->prev->next = Head->next; // 尾结点前驱指向首节点
  36.         Head->next->prev = Tail->prev; // 首节点指向尾结点前驱
  37.         Tail->prev = NULL;                           // 尾结点首指针释放
  38.         Tail->next = NULL;                           // 尾结点尾指针释放
  39.         free(Tail);                                           // 释放尾结点堆内存
  40.         return true;
  41. }
  42. ​```
复制代码
删除链表指定数据节点后的节点
  1. /********************************************************************
  2. *
  3. *        name         :        DoubleCircLList_Del
  4. *        function :  中删
  5. *        argument :        @head:目标链表
  6. *                                @data:需删除的数据
  7. *
  8. *        retval         :  返回1成功0失败
  9. *        author         :  17647576169@163.com
  10. *        date         :  2024-4-24
  11. *         note         :
  12. *
  13. * *****************************************************************/
  14. bool DoubleCircLList_Del(DoubleCircLList_t *Head, DataType_t data)
  15. {
  16.         // 备份首节点地址
  17.         DoubleCircLList_t *Phead = Head;
  18.         // 备份头节点地址
  19.         DoubleCircLList_t *Temp = Head->next;
  20.         // 1.判断链表是否为空,如果为空
  21.         if (Head == Head->next)
  22.         {
  23.                 perror("Linked lists have no data\n");
  24.                 return false;
  25.         }
  26.         // 删除的节点在头
  27.         if (data == Head->next->data)
  28.         {
  29.                 DoubleCircLList_HeadDel(Head);
  30.                 return true;
  31.         }
  32.         // 遍历找的目标数据节点
  33.         DoubleCircLList_t *P = NULL; // 定义变量保存找的目标数据的节点地址
  34.         while (Head->next != Temp->next)
  35.         {
  36.                 Temp = Temp->next;
  37.                 if (data == Temp->data)
  38.                 {
  39.                         P = Temp;
  40.                         break;
  41.                 }
  42.         }
  43.         // 找不到目标数据
  44.         if (NULL == P)
  45.         {
  46.                 perror("The target data cannot be found\n");
  47.                 return false;
  48.         }
  49.         // 目标数据在尾部
  50.         if (Head->next == P->next)
  51.         {
  52.                 DoubleCircLList_TailDel(Head);
  53.         }
  54.         else
  55.         {
  56.                 P->next->prev = P->prev; // 删除节点的后继指向删除节点的前驱
  57.                 P->prev->next = P->next; // 删除节点的前驱指向删除节点的后继
  58.                 P->next = NULL;                         // 删除节点的首指针释放
  59.                 P->prev = NULL;                         // 删除节点的尾指针释放
  60.                 free(P);                                 // 释放删除节点的堆内存
  61.         }
  62.         return true;
  63. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

数据人与超自然意识

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表