数据结构——双向循环链表
本文最后更新于 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*/
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇