数据结构 链表的构建——增删

/*************************************************
 *
 *   file name:LkList.c
 *   author   :momolyl@126.com
 *   date     :2024/04/22
 *   function :通过构建链表学习顺序存储
 *   note     :None
 *
 *   CopyRight (c) 2024    momolyl@126.com    All Right Reseverd
 *
 **************************************************/
#include <stdbool.h>
#include <stdlib.h>
/*************************************************
 *
 *   func name     :
 *   func function :
 *   func parameter:
 *
 *
 *   return        :None
 *   note          :None
 *   func author   :momolyl@126.com
 *   date          :2024/04/19
 *   version       :V1.0
 **************************************************/
// 结构体用于构建链表节点(数据域+指针域)
typedef int Datatype_t;
typedef struct LkList
{
    Datatype_t Data;
    struct LkList *Next;
} LkList_t;

// 创建一个空链表,使用头节点
LkList_t *LkList_Create(void)
{

    LkList_t *Head = (LkList_t *)calloc(1, sizeof(LkList_t)); // 为头节点申请内存,并错误处理
    if (NULL == Head)
    {
        perror("calloc memory for LkList if failed!\n");
        exit(-1);
    }
    Head->Next = NULL; // 将头节点的指针域指向NULL
    return Head;       // 返回头节点的地址
}

// 创建一个新节点,并对新节点初始化(数据域+指针域)
LkList_t *LkList_NewNode(Datatype_t data)
{

    LkList_t *NewNode = (LkList_t *)calloc(1, sizeof(LkList_t)); // 为新节点申请一个地址,
    NewNode->Data = data;                                        // 初始化数据域
    NewNode->Next = NULL;                                        // 初始化指针域
    return NewNode;
}

// 向链表中头插一个新节点
void LkList_HeadAdd(LkList_t *Head, Datatype_t data)
{

    LkList_t *NewNode = LkList_NewNode(data);
    if (NULL == Head->Next) // 判断链表是否为空
    {
        // 链表为空
        Head->Next = NewNode;
        return;
    }
    // 2.2链表非空
    {
        NewNode->Next = Head->Next;
        Head->Next = NewNode;
    }
}

// 向链表中尾插一个新节点
void LkList_TailAdd(LkList_t *Head, Datatype_t data)
{

    LkList_t *NewNode = LkList_NewNode(data);
    if (NULL == Head->Next) // 判断链表是否为空
    {
        // 链表为空
        Head->Next = NewNode;
        return;
    }
    // 2.2链表非空

    LkList_t *Phead = Head; // 备份链表的头节点地址
    while (Phead->Next)     // 遍历节点找到尾端
    {
        Phead = Phead->Next;
    }
    // 在尾端插入新节点
    {
        Phead = NewNode; // 将新节点的地址赋值给最后一个节点的指针域
    }
}
// 在链表中头删一个节点
bool LkList_HeadDel(LkList_t *Head)
{
    // 判断链表是否为空
    if (Head->Next)
        return false;                 // 为空则删除失败
    LkList_t *FirstNode = Head->Next; // 备份首节点地址
    Head->Next = Head->Next->Next;    // 将首节点的直接后继节点的地址赋值给头节点的指针域
    Head->Next->Next = NULL;          // 断开首节点与其直接后继节点的链接
    free(FirstNode);                  // 释放原首节点的地址,并将指针指向NULL
    FirstNode = NULL;
    return true;
}

// 在链表中尾删一个节点
bool LkList_HeadDel(LkList_t *Head)
{

    if (Head->Next)         // 判断链表是否为空
        return false;       // 为空则删除失败
    LkList_t *Phead = Head; // 备份链表的头节点地址
    while (Phead->Next)     // 遍历节点找到尾端
    {
        Phead = Phead->Next;
    }
    LkList_t *LastNode = Phead; // 备份尾节点地址
    Phead = NULL;               // 将尾节点的直接前驱指针域指向NULL
    free(LastNode);             // 释放尾节点的地址
    LastNode = NULL;            // 将尾节点的指针指向NULL
    return true;
}

// 根据节点的数据域指定删除一个节点(首尾节点的情况还没考虑到,太困了肝不动了4.23,明天再优化)
bool LkList_AppointDel(LkList_t *Head, Datatype_t data)
{
    if (Head->Next)             // 判断链表是否为空
        return false;           // 为空则删除失败
    LkList_t *Phead = Head;     // 备份链表的头节点地址
    while (Phead->Next == data) // 遍历节点找到指定数据的节点的直接前驱地址
    {
        Phead = Phead->Next;
    }
    LkList_t *AppointNode = Phead;   // 备份指定数据的节点的直接前驱地址
    Phead->Next = Phead->Next->Next; // 将指定节点的直接前驱指针域指向定节点的直接后继节点的地址
    AppointNode->Next->Next = NULL;  // 将指定节点的指针域指向NULL
    free(AppointNode->Next);         // 释放指定节点的地址
    AppointNode->Next = NULL;        // 将指定节点的指针指向NULL

    return true;
}

int main(void)
{
    LkList_Create();
    return 0;
}

posted @   铃是铃铛的铃  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示