本文最后更新于 153 天前,其中的信息可能已经有所发展或是发生改变。
数据结构——双向循环链表
1.文件注释内容
/**
* @filename: cirdblist.c
* @brief: cirdblist
* @author: philia
* @date: 2026/2/4
* @version: ver1.0
* @note none
* CopyRight (c) 2026 philia All Right Reseverd
*/2.头文件
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>3.定义管理结构体和初始化链表
typedef struct linklist
{
int data;
struct linklist *next;
struct linklist *prev;
} 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;
node->prev = node;
}
return node;
}
// 初始化
lklist_t *linklist_init()
{
return create_node(0); // 头节点 data 域通常不使用
}4.头插法
// 1. 头插法
bool headadd(lklist_t *link, int value)
{
lklist_t *node = create_node(value);
if (!node)
return false;
// 链表为空
if (link->next == link)
{
link->next = node;
return true;
}
// 链表非空
node->next = link->next;
node->prev = link->next->prev;
link->next->prev->next = node;
link->next->prev = node;
link->next = node;
return true;
}5.尾插法
// 2. 尾插法
bool lastadd(lklist_t *link, int value)
{
lklist_t *node = create_node(value);
if (!node)
return false;
// 链表为空
if (link->next == link)
{
link->next = node;
return true;
}
// 链表非空
node->next = link->next;
link->next->prev->next = node;
node->prev = link->next->prev;
link->next->prev = node;
return true;
}6.中间插法
// 3. 中间插入:在匹配值的后面插入
bool middleadd(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 *phead = link;
while (phead->next)
{
phead = phead->next;
if (phead->data == dest)
{
node->next = phead->next;
phead->next->prev = node;
phead->next = node;
node->prev = phead;
return true;
}
if (phead->next == link->next)
{
break;
}
}
printf("目标值不存在!\n");
return false;
}7.头删法
// 头删法
bool headdel(lklist_t *link)
{
// 链表为空
if (link->next == link)
{
printf("链表为空,删除失败!\n");
return 0;
}
// 链表非空
lklist_t *firstnode = link->next;
link->next->prev->next = link->next->next;
link->next->next->prev = link->next->prev;
link->next = link->next->next;
firstnode->prev = NULL;
firstnode->next = NULL;
free(firstnode);
return true;
}8.尾删法
// 尾删法
bool lastdel(lklist_t *link)
{
// 链表为空
if (link->next == link)
{
printf("链表为空,删除失败!\n");
return 0;
}
// 链表非空
link->next->prev->prev->next = link->next;
link->next->prev->prev->next = link->next;
link->next->prev->prev = NULL;
link->next->prev->next = NULL;
free(link->next->prev);
link->next->prev = link->next->prev->prev;
return true;
}9.中间删
// 中间删法
bool middledel(lklist_t *link, int dest)
{
// 链表为空
if (link->next == link)
{
printf("链表为空,删除失败!\n");
return false;
}
// 链表非空
lklist_t *phead = link;
while (phead->next)
{
phead = phead->next;
if (phead->data == dest)
{
if (phead->prev->next == link->next)
{
headdel(link);
return true;
}
phead->prev->next = phead->next;
phead->next->prev = phead->prev;
phead->next = NULL;
phead->prev = NULL;
free(phead);
return true;
}
if (phead->next == link->next)
{
break;
}
}
printf("没有找到目标点!\n");
return false; // 没找到目标点
}10.内存释放
// 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);
}11.链表遍历
// 遍历双向循环链表
void linklist_printf(lklist_t *link)
{
lklist_t *phead = link;
if (link->next == link)
{
printf("链表为空,遍历失败!\n");
return;
}
while (phead->next)
{
phead = phead->next;
printf("data = %d\n", phead->data);
if (phead->next == link->next)
{
break;
}
}
return;
}12.编写main函数进行测试
int main()
{
lklist_t *link = linklist_init();
headadd(link, 7);
headadd(link, 8);
headadd(link, 9);
headadd(link, 10);
middleadd(link, 145, 10);
linklist_printf(link);
return 0;
/*
data = 10
data = 145
data = 9
data = 8
data = 7*/
}


