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

发送评论 编辑评论


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