找回密码
 立即注册
首页 业界区 业界 2.单向循环链表的接口设计

2.单向循环链表的接口设计

准挝 2025-8-1 01:39:29
  1. /****************************************************************************
  2. *
  3. * file name: 2025-07-11_CircularLinkedList.c
  4. * author   : 15515376695@163.com
  5. * date     : 2025-07-11
  6. * function : 该程序设计单向循环链表的接口
  7. * note     : None
  8. * CopyRight (c)   2025  15515376695@163.com   Right Reseverd
  9. *
  10. ****************************************************************************/
  11. //用户可以根据自己的需要进行修改所需的数据类型
  12. typedef int DataType_t;
  13. //构造单向循环链表的结点,链表中所有结点的数据类型应该是相同的
  14. typedef struct CircularLinkedList
  15. {
  16.         DataType_t   data;         //记录结点的数据域
  17.         struct CircularLinkedList  *next; //记录结点的指针域
  18. }CircLList_t;
  19. //创建一个空单向循环链表,空链表应该有一个头结点,对链表进行初始化
  20. CircLList_t * CircLList_Create(void)
  21. {
  22.         //1.使用calloc为单向循环链表的头结点从堆空间申请一块内存,对链表进行初始化
  23.         CircLList_t * Head = (CircLList_t *)calloc(1,sizeof(CircLList_t));
  24.     if (NULL == Head)
  25.     {
  26.             perror("calloc memory for Head is failed");
  27.             exit(-1);//程序终止
  28.     }
  29.     //2.对头结点进行初始化,头结点是不存储数据域,指针域指向自身,体现“循环”思想
  30.     Head->next = Head;
  31.     //3.把头结点的地址返回
  32.    
  33.     return Head;
  34. }
  35. //创建新的结点,并对其初始化(数据域+指针域)
  36. CircLList_t * CircLList_NewNode(DataType_t data)
  37. {
  38.         //1.创建一个新的结点并申请内存
  39.         CircLList_t *New = (CircLList_t *)calloc(1,sizeof(CircLList_t));
  40.         if (NULL == New)
  41.         {
  42.                 perror("calloc memory for NewNode is Failed");
  43.                 return NULL;
  44.         }
  45.         //2.对新结点进行初始化
  46.         New->data = data;
  47.         New->next = NULL;
  48.     return New;
  49. }
  50. //单向循环链表头部插入
  51. bool CircLList_HeadInsert(CircLList_t *Head,DataType_t data)
  52. {
  53.         //1.创建新的结点,并进行初始化
  54.         CircLList_t *New = CircLList_NewNode(data);
  55.         if (NULL == New)
  56.         {
  57.                 printf("can not insert newnode\n");
  58.                 return false;
  59.         }
  60.         //2.判断链表是否为空,如果为空,直接插入
  61.         if (Head->next == Head)
  62.         {
  63.                 Head->next = New;
  64.                 New->next = New;
  65.                 return true;
  66.         }
  67.         //3.若链表为非空,则把新结点插入链表头部
  68.         //先遍历找到尾结点地址
  69.         CircLList_t *Phead = Head->next;//备份首结点地址
  70.         //遍历寻找尾结点
  71.         while(Phead->next != Head->next)
  72.         {
  73.                 Phead = Phead->next;//        得到尾结点地址
  74.         }
  75.         //进行头插
  76.         Phead->next = New;
  77.         New->next = Head->next;
  78.         Head->next = New;
  79.         return true;
  80. }
  81. ////单向循环链表尾部插入
  82. bool CircLList_TailInsert(CircLList_t *Head,DataType_t data)
  83. {
  84.         CircLList_t *New = CircLList_NewNode(data);
  85.         if (NULL == New)
  86.         {
  87.                 printf("can not insert ner node\n");
  88.                 return false;
  89.         }
  90.         if (Head->next == Head)
  91.         {
  92.                 Head->next = New;
  93.                 New->next = New;
  94.                 return true;
  95.         }
  96.         //若链表非空
  97.         CircLList_t *Phead = Head->next;//备份首结点地址
  98.         while(Phead->next != Head->next)
  99.         {
  100.                 Phead = Phead->next;//        得到尾结点地址
  101.         }
  102.         //进行尾部插入
  103.         Phead->next = New;
  104.         New->next = Head->next;
  105.         return true;
  106. }
  107. //向单向循环链表指定位置插入一个新的结点
  108. bool CircLList_AppointInsert(CircLList_t *Head,DataType_t data,DataType_t DestVal)
  109. {
  110.         CircLList_t * New = CircLList_NewNode(data);
  111.         if (NULL == New)
  112.         {
  113.                 printf("can not insert ner node\n");
  114.                 return false;
  115.         }
  116.         if (Head->next == Head)
  117.         {
  118.                 Head->next = New;
  119.                 New->next = New;
  120.                 return true;
  121.         }
  122.         //若链表非空
  123.         CircLList_t * Phead = Head->next;
  124.         while(Phead->data != DestVal)
  125.         {
  126.                 Phead = Phead->next;
  127.                 if (Phead->next == Head->next && Phead->data != DestVal)
  128.                 {
  129.                         printf("The DestVal doesn't exist! \n");
  130.             return false;
  131.                 }
  132.         }
  133.         //找到目标节点
  134.         New->next = Phead->next;
  135.         Phead->next = New;
  136.         return true;
  137.        
  138. }
  139. //头删
  140. bool CircLList_HeadDel(CircLList_t *Head)
  141. {
  142.         CircLList_t * Phead = Head->next;//备份首结点地址
  143.         CircLList_t *Temp = Head->next;
  144.         //判断链表是否为空
  145.         if (Head->next == Head)
  146.         {
  147.                 printf("CircLList is empty\n");
  148.                 return false;
  149.         }
  150.         //判断是否只含有首结点
  151.         if (Head->next->next == Phead)
  152.         {
  153.                 Head->next = Head;
  154.                 Phead->next = NULL;//首结点的指针域指向NULL,目的是防止野指针出现和内存泄漏
  155.                 free(Phead);//释放结点内存,防内存泄漏
  156.                 return true;
  157.         }
  158.         //如果为非空,且含有多个结点,
  159.         //遍历找到尾结点
  160.         while(Phead->next != Head->next)
  161.         {
  162.                 Phead = Phead->next;
  163.         }
  164.         Phead->next = Head->next->next;
  165.         Head->next = Head->next->next;
  166.         Temp->next = NULL;
  167.         free(Temp);
  168.         return true;
  169. }
  170. //中删
  171. bool CircLList_DestDel(CircLList_t *Head, DataType_t dest)
  172. {
  173.     // 检查头指针是否有效(防止空指针访问)
  174.     if (Head == NULL)
  175.     {
  176.         printf("Error, Head pointer is NULL! \n");
  177.         return false;
  178.     }
  179.     CircLList_t *Current = Head->next; // 指向首节点(若为空链表则指向头节点)
  180.     CircLList_t *Prev = Head;          // 指向Current的前一个节点
  181.     // 1. 判断链表是否为空(头节点的next指向自身)
  182.     if (Head->next == Head)
  183.     {
  184.         printf("Error, CircularLinkList is empty! \n");
  185.         return false;
  186.     }
  187.     // 2. 查找目标节点
  188.     while (Current->data != dest)
  189.     {
  190.         Prev = Current;
  191.         Current = Current->next;
  192.         // 若遍历一圈回到首节点,说明未找到目标
  193.         if (Current == Head->next)
  194.         {
  195.             printf("The target doesn't exist! \n");
  196.             return false;
  197.         }
  198.     } // 退出循环时,Current指向目标节点,Prev指向其前驱
  199.     // 3. 分情况删除目标节点
  200.     // 3.1目标是首节点
  201.     if (Current == Head->next)
  202.     {
  203.         // 3.1.1 链表只有一个节点(首节点的next指向头节点)
  204.         if (Current->next == Head->next)
  205.         {
  206.             Head->next = Head; // 恢复为空链表
  207.         }
  208.         // 3.1.2 链表有多个节点
  209.         else
  210.         {
  211.             // 找到尾节点(尾节点的next指向首节点)
  212.             CircLList_t *Tail = Head->next;
  213.             while (Tail->next != Head->next)
  214.             {
  215.                 Tail = Tail->next;
  216.             }
  217.             // 尾节点指向新首节点,头节点更新新首节点
  218.             Tail->next = Current->next;
  219.             Head->next = Current->next;
  220.         }
  221.     }
  222.     // 3.2 目标是尾节点(尾节点的next指向首节点)
  223.     else if (Current->next == Head->next)
  224.     {
  225.         Prev->next = Head->next; // 前驱直接指向首节点
  226.     }
  227.     // 3.3 目标是中间节点
  228.     else
  229.     {
  230.         Prev->next = Current->next; // 前驱指向目标的后继
  231.     }
  232.     // 释放目标节点内存
  233.     free(Current);
  234.     return true;
  235. }
  236. //尾删
  237. bool CircLList_TailDel(CircLList_t *Head)
  238. {
  239.     CircLList_t *Current = Head->next;
  240.     CircLList_t *Prev = Head;         
  241.     // 1.判断单向循环链表是否为空
  242.     if (Head->next == Head)
  243.     {
  244.         printf("Error,  CircularLinkList is empty! \n");
  245.         return false;
  246.     }
  247.     // 2.若单向循环链表非空
  248.     // 若链表只有首结点
  249.     if (Current->next == Head->next)
  250.     {
  251.         Head->next = Head; // 空链表状态
  252.         Current->next = NULL;
  253.         free(Current); // 防止内存泄漏
  254.         return true;
  255.     }
  256.     // 若还有别的结点
  257.     while (Current->next != Head->next) // 不断向下检查结点指针域
  258.     {
  259.         Prev = Current;
  260.         Current = Current->next;         
  261.     }
  262.     // Current到达未尾结点 Prev为Current 的前一个位置
  263.     Prev->next = Head->next; // 新尾结点链接首结点, 行成循环
  264.     Current->next = NULL;
  265.     free(Current); // 防止内存泄漏
  266.     return true;
  267. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册