链表 -- 环链表

环链表的创建

复制代码
  4 node_t *clinklist_create(void)
  5 {
  6     node_t*phead=malloc(sizeof(node_t));
  7     if(phead==NULL)
  8     {
  9         printf("malloc fail");
 10         return NULL;
 11     }
 12     phead->next=phead;
 13     return phead;
 14 }

与普通链表区分,这里头节点指向自己

环链表的头插入

复制代码
 16 void clinlist_insert_head(node_t*phead,data_t d)
 17 {
 18     node_t*p_new=malloc(sizeof(node_t));
 19     if(phead==NULL)
 20     {
 21         printf("malloc fail");                                                                                                                                                   
 22         return ;
 23     }
 24     if(phead->next==phead)     //只有头节点的情况
 25     {
 26         phead->next=p_new;
 27         p_new->next=p_new;
 28         p_new->data=d;
 29         return;
 30     }
 31     node_t*p_tail=phead->next;
 32     while(p_tail->next!=phead->next)   //其实也可以处理空链表的情况,下面是通用逻辑
 33         p_tail=p_tail->next;
 34     p_tail->next=p_new;
 35     p_new->next=phead->next;
 36     phead->next=p_new;
 37     p_new->data=d;
 38     return;
 39 }

这里采用的是头节点没有有效数据,头节点不参与环的插入方法,若头节点插入环实现起来会相对简单

打印环链表

复制代码
 41 void clinklist_printf(node_t*phead)
 42 {
 43     if(phead==NULL)
 44         return;
 45     node_t*p=phead->next;
 46     if(p==phead)
 47         return;
 48     if(p->next==p)
 49     {
 50         printf("%d ",p->data);    //此处特殊处理除了头节点只有一个节点的情况,下面的通用逻辑也是可以处理的
 51         return;
 52     }
 53     printf("%d ",p->data);
 54     p=p->next;
 55     while(p!=phead->next)
 56     {
 57         printf("%d ",p->data);
 58         p=p->next;
 59     }
 60     return;
 61 }

以头节点指向的首节点作为截止标志来作为结束条件

环链表的查找

复制代码
 63 node_t* clinklist_find_key(node_t*phead,data_t key)
 64 {
 65     node_t*p=phead->next;
 66     if(p==phead)
 67         return NULL;
 68     if(p->data==key)
 69         return p;
 70     p=p->next;
 71     while(p->data!=key && p!=phead->next)
 72         p=p->next;
 73     if(p->data==key)
 74         return p;
 75     return NULL;
 76 }

环链表的尾删除

复制代码
78 void clinklist_del_tail(node_t*phead)         //删除的是头结点指向的首节点的前一个节点
 79 {
 80     if(phead==NULL || phead->next==phead)
 81         return;
 82     node_t*p=phead->next;
 83     while(p->next->next!=phead->next)
 84         p=p->next;
 85     node_t*p_del=p->next;
 86     if(phead->next==p_del)                    //避免单节点情况下头结点的悬空指针
 87         phead->next=phead;
 88     p->next=phead->next;
 89     free(p_del);
 90 }

环链表的头删除

复制代码
 92 void clinklist_del_head(node_t*phead)
 93 {
 94     if(phead==NULL || phead->next==phead)
 95         return;
 96     node_t*p_tail=phead->next;
 97     while(p_tail->next != phead->next)
 98     {
 99         p_tail=p_tail->next;
100     }
101     node_t*p_del=phead->next;
102     phead->next=p_del->next;
103     p_tail->next=p_del->next;
104     free(p_del);
105 }

环链表的销毁

复制代码
107 void clinklist_destroy(node_t**phead)
108 {
109     if(phead==NULL || *phead==NULL)
110         return;
111     if((*phead)->next==*phead)
112     {
113         free(*phead);
114         *phead=NULL;
115         return;
116     }
117     if((*phead)->next==(*phead)->next->next)
118     {
119         free((*phead)->next);
120         free(*phead);
121         *phead=NULL;
122         return;
123     }
124     node_t*p=(*phead)->next->next;
125     node_t*p_del=(*phead)->next->next;
126     while(p!=(*phead)->next)
127     {
128         p=p_del->next;
129         free(p_del);
130         p_del=p;
131     }
132     free(p);
133     free(*phead);
134     *phead=NULL;
135 }
相关推荐
imaol11 小时前
链表 -- 双向链表
java·前端·链表
东风破_1 小时前
大前端手里的 Next.js:从 #root 到 SEO,一份 HTML 的两种命运
前端·后端
IT_陈寒2 小时前
Vue的v-for不听话?我被这个Key的坑整懵了
前端·人工智能·后端
2601_963869952 小时前
【计算机毕业设计】基于Java的相框定制系统的设计与实现
java·开发语言·课程设计
王林不想说话2 小时前
ES6 到 ES2026 全面进阶指南:新特性、原理、示例与工程落地
前端·javascript·面试
用户43523713814932 小时前
🚀 Vue3 + TypeScript 学习笔记:从泛型 T 到 Promise<T>,终于搞懂了 keyof 和 typeof
前端
跟着群主去吃肉2 小时前
Cinemachine的应用-第三人称视角
前端·unity3d·游戏开发
东方小月2 小时前
从零开发一个 Coding Agent(十):实现 CLI 参数解析与静态命令
前端·人工智能·开源
阿黎梨梨2 小时前
Next.js 全栈开发:从 SPA 的痛点到 SSR 的破局之道
前端·后端