数据结构——双向链表
本文最后更新于 154 天前,其中的信息可能已经有所发展或是发生改变。

1.文件注释内容

/**
 * @filename:    doublinklist.c
 * @brief:       doublinklist
 * @author:      philia
 * @date:        2026/2/2
 * @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 = NULL;
        node->prev = NULL;
    }
    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->next = node;
        return true;
    }
    //链表非空
    node->next = link->next;
    node->next->prev = node;
    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->next = node;
        return true;
    }
    //链表非空
    lklist_t *curr = link->next;
    while(curr->next){
        curr = curr->next;
    }
    curr->next = node;
    node->prev = curr;

    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->next = node;
        return true;
    }
    //链表非空
    lklist_t *curr = link;
    while(curr->next){
        curr = curr->next;
        if(curr->data == dest)
        {   
            if(curr->next == NULL)
            {
                curr->next = node;
                node->prev = curr;
                return true;
            }
            node->next = curr->next;
            curr->next->prev = node;
            curr->next = node;
            node->prev = curr;
            return true;
        }
    }
    printf("没有找到目标点!\n");
    return false;
}

7.头删法

//头删法
bool headdel(lklist_t *link) {
    //链表为空
    if(!link->next)
    {
        printf("链表为空,删除失败!\n");
        return 0;
    }
    //链表非空
    lklist_t* firstnode = link->next;
    link->next = link->next->next;
    link->next->prev = NULL;
    firstnode->next = NULL;
    free(firstnode);
    return true;
}

8.尾删法

//尾删法
bool lastdel(lklist_t *link) {
    //链表为空
    if(!link->next)
    {
        printf("链表为空,删除失败!\n");
        return 0;
    }
    //链表非空
    lklist_t *curr = link->next;
    while(curr->next){
        curr = curr->next;
    }
    curr->prev->next = NULL;
    curr->prev = NULL;
    free(curr);

    return true;
}

9.中间删

bool middledel(lklist_t *link, int dest) {
    if (!link->next) {
        printf("链表为空,删除失败!\n");
        return false;
    }

    lklist_t *curr = link->next;  // 直接从第一个数据节点开始遍历
    while (curr) {
        if (curr->data == dest) {
            // 处理前驱和后继的指针
            lklist_t *prev = curr->prev;  // 可能为 NULL
            lklist_t *next = curr->next;  // 可能为 NULL

            // 如果存在前驱节点,修改前驱的next
            if (prev) {
                prev->next = next;
            } else {
                // 删除的是首节点:更新头节点的next
                link->next = next;
            }

            // 如果存在后继节点,修改后继的prev
            if (next) {
                next->prev = prev;
            }

            // 清空指针并释放(可选)
            curr->next = NULL;
            curr->prev = NULL;
            free(curr);
            return true;
        }
        curr = curr->next;
    }

    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){
        printf("链表为空,遍历失败!\n");
        return;
    }
    while(link->next)
    {   
        link = link->next;
        printf("data = %d\n",link->data);

    }
    return;
}

12.编写main函数进行测试

int main()
{   lklist_t *link = linklist_init();
    addhead(link,1);
    addhead(link,2);
    addhead(link,3);
    addhead(link,9);
    middledel(link,1);
    linklist_printf(link);
    linklist_destroy(link);
    return 0;
    /*
    data = 9
    data = 3
    data = 2*/
}
暂无评论

发送评论 编辑评论


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