本文最后更新于 198 天前,其中的信息可能已经有所发展或是发生改变。
数据结构——单向循环链表
1.文件注释内容
/**
* @filename: cirlinklist.c
* @brief: cirlinklist
* @author: kun
* @date: 2026/2/1
* @version: ver1.0
* @note none
* CopyRight (c) 2026 name All Right Reseverd
*/2.头文件
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>3.定义管理结构体和初始化链表
typedef struct linklist {
int data;
struct linklist *next;
} lklist_t;
// 统一分配内存的逻辑,减少重复代码
lklist_t* create_node(int value) {
lklist_t *node = (lklist_t *)calloc(1, sizeof(lklist_t));
if (node) {
node->data = value;
node->next = node; //头节点自己指向自己,提现循环思想
}
return node;
}
// 初始化
lklist_t* linklist_init() {
return create_node(0); // 头节点 data 域通常不使用
}4.头插法
//头插法
bool addhead(lklist_t* link,int value)
{ //初始化新结点
lklist_t* node = create_node(value);
if(!node)return false;
//链表为空
if(link->next == link)
{
link->next = node;
return true;
}
//链表非空
lklist_t *curr = link->next;
while(curr->next != link->next){
curr = curr->next;
}
curr->next = node;
node->next = link->next;
link->next = node;
return true;
}5.尾插法
//尾插法
bool addlast(lklist_t* link,int value)
{ //初始化新结点
lklist_t* node = create_node(value);
if(!node)return false;
//链表为空
if(link->next == link)
{
link->next = node;
return true;
}
//链表非空
lklist_t *curr = link->next;
while(curr->next != link->next){
curr = curr->next;
}
curr->next = node;
node->next = link->next;
return true;
}6.中间插法
//中间插入
bool addmiddle(lklist_t *link, int value, int dest) {
//初始化新结点
lklist_t* node = create_node(value);
if(!node)return false;
//链表为空
if(link->next == link)
{
link->next = node;
return true;
}
//链表非空
lklist_t *curr = link;
while (curr != link->next) {
curr = curr->next;
if (curr->data == dest) {
node->next = curr->next;
curr->next = node;
return true;
}
}
printf("没找到目标点!\n");
return false; // 没找到目标点
}7.头删法
//头删法
bool headdel(lklist_t* link)
{
//链表为空
if(link->next == link)
{
printf("链表为空,删除失败!\n");
return false;
}
//链表非空
while(link->next == link->next->next)
{
link->next->next = NULL;
free(link->next);
link->next = link;
return true;
}
lklist_t *curr = link->next;
while(curr->next != link->next)
{
curr = curr->next;
}
curr->next = link->next->next;
link->next->next = NULL;
free(link->next);
link->next = curr->next;
return true;
}8.尾删法
//尾删法
bool lastdel(lklist_t* link)
{
//链表为空
if(link->next == link)
{
printf("链表为空,删除失败!\n");
return false;
}
//链表非空
while(link->next == link->next->next)
{
link->next->next = NULL;
free(link->next);
link->next = link;
return true;
}
lklist_t *curr = link->next;
lklist_t *lastprev;
while(curr->next != link->next)
{ lastprev = curr;
curr = curr->next;
}
lastprev->next = link->next;
curr->next = NULL;
free(curr);
return true;
}9.中间删法
//中间删除
bool middledel(lklist_t *link, int value) {
// 空链表判断
if (link->next == link) {
printf("链表为空,删除失败!\n");
return false;
}
lklist_t *first = link->next; // 第一个数据节点
// 情况1:要删除的是第一个节点
if (first->data == value) {
// 如果链表仅有一个节点
if (first->next == first) {
free(first);
link->next = link; // 头节点指向自己,链表置空
return true;
}
// 链表有多个节点:找到尾节点
lklist_t *tail = first;
while (tail->next != first) {
tail = tail->next;
}
// 删除第一个节点,并更新尾节点的 next 指向新的第一个节点
link->next = first->next; // 头节点指向第二个节点
tail->next = link->next; // 尾节点指向新的第一个节点,保持循环
free(first);
return true;
}
// 情况2:删除的不是第一个节点(可能是中间或尾节点)
lklist_t *prev = first; // 从第一个节点开始作为前驱
lklist_t *curr = first->next; // 从第二个节点开始查找
while (curr != first) { // 遍历一圈回到第一个节点时停止
if (curr->data == value) {
prev->next = curr->next; // 前驱绕过当前节点
free(curr);
return true;
}
prev = curr;
curr = curr->next;
}
printf("未找到值为 %d 的节点\n", value);
return false;
}7.内存释放
// 4. 记得释放内存!
void linklist_destroy(lklist_t *link) {
lklist_t *curr = link;
while (curr->next != link->next) {
lklist_t *next = curr->next;
free(curr);
curr = next;
}
free(curr);
}8.链表遍历
//遍历链表
void printlinklist(lklist_t* link)
{
//链表为空
if(link->next == link)
{
printf("链表为空,遍历失败!\n");
return;
}
//链表非空
lklist_t *phead = link;
while(phead->next)
{
phead = phead->next;
printf("data = %d\n",phead->data);
if(phead->next == link->next)
{
break;
}
}
return;
}9.编写main函数进行测试
int main()
{
lklist_t* link = linklist_init();
addhead(link,5);
addhead(link,6);
addhead(link,7);
addhead(link,8);
middledel(link,59);
printlinklist(link);
return 0;
/*未找到值为 59 的节点
data = 8
data = 7
data = 6
data = 5*/
}


