首页 > 其他分享 >自定义单链表(非循环)的基本接口函数

自定义单链表(非循环)的基本接口函数

时间:2024-05-07 20:13:23浏览次数:51  
标签:结点 单链 自定义 Head next 链表 LList Phead 接口函数

文件描述及头文件包含

/*******************************************************************
 *
 *	文件名称  :	单链表(非循环)的基本接口程序
 *	文件作者  : [email protected]
 *	创建日期  :  2024/05/07
 *	文件功能  :  对单链表的增删改查功能的定义
 *	注意事项  :  None
 *
 *	CopyRight (c)  2024   [email protected]   All Right Reseverd
 *
 * *****************************************************************/
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>

定义数据类型,构造链表结点结构体

// 指的是单向链表中的结点有效数据类型,用户可以根据需要进行修改
typedef int DataType_t;

// 构造链表的结点,链表中所有结点的数据类型应该是相同的
typedef struct LinkedList
{
    DataType_t data;         // 结点的数据域
    struct LinkedList *next; // 结点的指针域

} LList_t;

创建链表

/*******************************************************************
 *
 *	函数名称:	LList_Create
 *	函数功能:   创建一个空链表,空链表应该有一个头结点,对链表进行初始化
 *	函数参数:
 *	返回结果:
 *			    @Head	返回创建成功后的头结点地址
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/

// 创建一个空链表,空链表应该有一个头结点,对链表进行初始化
LList_t *LList_Create(void)
{
    // 1.创建一个头结点并对头结点申请内存
    LList_t *Head = (LList_t *)calloc(1, sizeof(LList_t));
    if (NULL == Head)
    {
        perror("Calloc memory for Head is Failed");
        exit(-1);
    }

    // 2.对头结点进行初始化,头结点是不存储有效内容的!!!
    Head->next = NULL;

    // 3.把头结点的地址返回即可
    return Head;
}

新结点创建

/*******************************************************************
 *
 *	函数名称:	LList_NewNode
 *	函数功能:   创建新的结点,并对新结点进行初始化(数据域 + 指针域)
 *	函数参数:
 *              @data       传入需要新建结点数据域的值
 *	返回结果:
 *			    @New	返回创建成功后的新结点地址
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
// 创建新的结点,并对新结点进行初始化(数据域 + 指针域)
LList_t *LList_NewNode(DataType_t data)
{
    // 1.创建一个新结点并对新结点申请内存
    LList_t *New = (LList_t *)calloc(1, sizeof(LList_t));
    if (NULL == New)
    {
        perror("Calloc memory for NewNode is Failed");
        return NULL;
    }
    // 2.对新结点的数据域和指针域进行初始化
    New->data = data;
    New->next = NULL;
    return New;
}

头插法插入新结点

/*******************************************************************
 *
 *	函数名称:	LList_HeadInsert
 *	函数功能:   向链表的头部插入新结点
 *	函数参数:
 *              @Head   传入需要操作的链表的头结点
 *              @data   传入需要插入的数据
 *	返回结果:
 *			    @bool	返回插入是否成功
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
// 头插
bool LList_HeadInsert(LList_t *Head, DataType_t data)
{
    // 1.创建新的结点,并对新结点进行初始化
    LList_t *New = LList_NewNode(data);
    if (NULL == New)
    {
        printf("can not insert new node\n");
        return false;
    }

    // 2.判断链表是否为空,如果为空,则直接插入即可
    if (NULL == Head->next)
    {
        Head->next = New;
        return true;
    }

    // 3.如果链表为非空,则把新结点插入到链表的头部
    New->next = Head->next;
    Head->next = New;

    return true;
}

尾插法插入新结点

/*******************************************************************
 *
 *	函数名称:	LList_TailInsert
 *	函数功能:   向链表的尾部插入新结点
 *	函数参数:
 *              @Head   传入需要操作的链表头结点地址
 *              @data   传入需要插入的结点的数据域的值
 *	返回结果:
 *			    @bool	返回插入是否成功
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
bool LList_TailInsert(LList_t *Head, DataType_t data)
{
    // 1.创建新的结点,并对新结点进行初始化
    LList_t *New = LList_NewNode(data);
    if (NULL == New)
    {
        printf("can not insert new node\n");
        return false;
    }

    // 2.判断链表是否为空,如果为空,则直接插入即可
    if (NULL == Head->next)
    {
        Head->next = New;
        return true;
    }

    // 3.如果非空,向后遍历到尾结点进行插入操作
    else
    {
        // 对链表的头文件的地址进行备份
        LList_t *Phead = Head;
        while (Phead->next)
        {
            Phead = Phead->next;
        }
        Phead->next = New;
    }
    return true;
}

目标结点后插入新结点

/*******************************************************************
 *
 *	函数名称:	LList_DestInsert
 *	函数功能:   向链表的指定节点后插入新结点
 *  函数参数:
 *              @Head   传入需要操作的链表头结点地址
 *              @dest   传入目标结点的数据域的值
 *              @data   传入需要插入的结点的数据域的值
 *	返回结果:
 *			    @bool	返回插入是否成功
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
bool LList_DestInsert(LList_t *Head, DataType_t dest, DataType_t data)
{
    // 1.对链表的头文件的地址进行备份
    LList_t *Phead = Head;
    // 2.判断链表中是否有目标结点
    while (Phead->next)
    {
        // 当存在目标结点时  停止循环
        if (Phead->data == dest)
        {
            break;
        }
        else
        {
            Phead = Phead->next;
        }
    }
    // 3.判断是否因为找到目标结点而停止循环
    if (Phead->next == NULL && Phead->data != dest)
    {
        return false;
    }

    // 4.向该结点后插入新结点 创建新的结点,并对新结点进行初始化
    LList_t *New = LList_NewNode(data);
    New->next = Phead->next;
    Phead->next = New;
    return true;
}

头删法删除结点

/*******************************************************************
 *
 *	函数名称:	LList_HeadDel
 *	函数功能:   删除首结点
 *  函数参数:
 *              @Head   传入需要操作的链表头结点地址
 *	返回结果:
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
bool LList_HeadDel(LList_t *Head)
{
    // 1.判断链表是否为空
    if (Head->next == NULL)
    {
        return false;
    }
    else
    {
        // 2.对链表的首结点的地址进行备份
        LList_t *Phead = Head->next;
        // 3.删除首结点
        Head->next = Phead->next; // 将头结点指向首结点的下一个结点
        Phead->next = NULL;       // 将原首结点的next指针指向NULL
        free(Phead);              // 释放原首结点的空间
        return true;
    }
}

尾删法删除结点

/*******************************************************************
 *
 *	函数名称:	LList_HeadDel
 *	函数功能:   删除尾结点
 *  函数参数:
 *              @Head   传入需要操作的链表头结点地址
 *	返回结果:
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
bool LList_TailDel(LList_t *Head)
{
    // 1.判断链表是否为空
    if (Head->next == NULL)
    {
        return false;
    }
    else
    {
        // 2.对链表的首结点及头结点的地址进行备份
        LList_t *temp = Head;
        LList_t *Phead = Head->next;
        // 3.遍历查找尾结点地址
        while (Phead->next)
        {
            temp = temp->next;
            Phead = Phead->next;
        }
        // 4.删除尾结点
        temp->next = NULL;
        free(Phead);
        return true;
    }
}

删除指定节点

/*******************************************************************
 *
 *	函数名称:	LList_DestDel
 *	函数功能:   删除指定结点
 *  函数参数:
 *              @Head   传入需要操作的链表头结点地址
 *              @dest   传入需要删除的目标结点
 *	返回结果:
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
bool LList_DestDel(LList_t *Head, DataType_t dest)
{
    // 1.判断链表是否为空
    if (Head->next == NULL)
    {
        return false;
    }
    else
    {
        // 2.对链表的首结点及头结点的地址进行备份
        LList_t *temp = Head;
        LList_t *Phead = Head->next;
        // 3.遍历链表寻找目标结点
        while (Phead)
        {
            if (Phead->data == dest) // 当前结点数据域的值与目标值相同时 跳出循环
            {
                break;
            }
            temp = temp->next; // 不同时  指针向后继续遍历
            Phead = Phead->next;
        }
        // 4.判断是否因为找到尾结点而结束
        if (Phead->next == NULL && Phead->data != dest)
        {
            return false;
        }
        else
        {
            temp->next = Phead->next; // 将目标结点直接前驱的next指针指向目标结点直接后继的地址
            Phead->next = NULL;       // 将目标节点的next指针指向NULL
            free(Phead);              // 释放目标结点的内存
            return true;
        }
    }
}

遍历打印所有结点

/*******************************************************************
 *
 *	函数名称:	LList_Print
 *	函数功能:   遍历打印所有结点
 *  函数参数:
 *              @Head   传入需要操作的链表头结点地址
 *	返回结果:
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
// 遍历
void LList_Print(LList_t *Head)
{
    // 对链表的头文件的地址进行备份
    LList_t *Phead = Head;

    // 首结点
    while (Phead->next)
    {
        // 把头的直接后继作为新的头结点
        Phead = Phead->next;

        // 输出头结点的直接后继的数据域
        printf("data = %d\n", Phead->data);
    }
}

测试主函数

/*******************************************************************
 *
 *	函数名称:	main
 *	函数功能:   主函数  用于测试自定义函数功能是否正确
 *  函数参数:
 *	返回结果:
 *	注意事项:   None
 *	函数作者:   [email protected]
 *	创建日期:   2024/05/06
 *	修改历史:
 *	函数版本:	V1.0
 * *****************************************************************/
int main()
{
    // 新建空链表
    LList_t *head = LList_Create();
    // 尾插法插入数据10  15
    LList_TailInsert(head, 10);
    LList_TailInsert(head, 15);
    LList_Print(head);
    printf("\n");
    // 头插法插入数据30  25  20  10  15
    LList_HeadInsert(head, 20);
    LList_HeadInsert(head, 25);
    LList_HeadInsert(head, 30);
    LList_Print(head);
    printf("\n");
    // 指定目标后插入数据30  25  20  5  10  15
    LList_DestInsert(head, 20, 5);
    LList_Print(head);
    printf("\n");
    // 头删25  20  5  10  15
    LList_HeadDel(head);
    LList_Print(head);
    printf("\n");
    // 尾删25  20  5  10
    LList_TailDel(head);
    LList_Print(head);
    printf("\n");
    // 指定删除目标结点25  5  10
    LList_DestDel(head, 20);
    LList_Print(head);
    printf("\n");
    return 0;
}

测试结果

image

标签:结点,单链,自定义,Head,next,链表,LList,Phead,接口函数
From: https://www.cnblogs.com/lzlwyh/p/18178268

相关文章

  • 自定义单链表(非循环)反转的基本函数接口
    题干structListNode*ReverseList(structListNode*head){if(head==NULL||head->next==NULL){returnhead;}else{structListNode*Phead=head;structListNode*temp=head->next;Phead->next=NULL;......
  • shell 脚本中使用自定义的alias别名
    摘自:https://blog.csdn.net/cscrazybing/article/details/41285287alias,假名,别名,bash的一个内建命令,用来给常用的较长的命令定义个简短的名称。alias命令的基本格式为alias[word[='command']],[]内为可选项。定义word为command的别名。若=’command’部分省略,则输出word......
  • ECharts自定义提示框浮层内容
    因为提示框内容支持字符串模板和回调函数两种形式字符串模板模板变量有{a},{b},{c},{d},{e},分别表示系列名,数据名,数据值等等,但是trigger属性为axis的时候它数据条就很多了,就可以用{a0},{a1},{a2}这样子去拿数据跟数组下标一样(官网有详细示例)示例:在`option`中的`tooltip`里边写......
  • Docker网络:Docker0、容器互联技术--link、自定义网络、实战部署Redis集群
    一、Docker网络●--理解Docker0在干净的Linux环境上安装docker(将docker的所有镜像、容器先删除,干干净净!)实验:1、查看本地网络信息ipaddr可见有三个网卡信息:lo:本地(回环)地址;ens:虚拟机或云服务器(内网)地址;docker0:docker网络地址。问题:docker是如何处理容器网络访问......
  • 【Python-Json】自定义类输入json序列化、json的读取与写入
    AI问答Questionjson支持numpy数组么Answer不幸的是,标准的JSON格式不直接支持NumPy数组.JSON是一种用于存储和交换数据的文本格式,它有限的数据类型只包括对象(object)、数组(array)、数字(number)、字符串(string)、布尔值(true/false)、空值(null)等.因此,无法直接将......
  • blazor中的PageTitle输出keywords和description,自定义组件
    在blazor的PageTitle中不具备输出keywords和description的功能,而如果直接使用<mate>标签,输出中文时会变成乱码,所以我给大家推介下面的代码解君愁:1@*<PageTitle>@Title-@AppTitle</PageTitle>*@2<HeadContent>3@(newMarkupString($"<metaname=\"keywords\"......
  • 基于1500/1200 PLC的webserver---用户自定义页面
    1.创建html页面页面需要包含字符集信息:<metahttp-equiv="content-type"content="text/html;charset=utf-8">包含AWP命令的html文件,大小限制为64KB最简单的页面自动刷新:<metahttp-equiv="Refresh"content="10">2.AWP指令AWP命令公式中""之......
  • 一起了解开源自定义表单的优势表现
    随着社会的进步和科技的发展,越来越多的中小企业希望采用更为先进的软件平台,助力企业实现高效率的流程化管理。低代码技术平台、开源自定义表单已经慢慢走入大众视野,成为一款灵活、高效的数字化转型工具。流辰信息专注于低代码技术平台的研发与创新工作,竭尽全力为通信业、电力、高......
  • 单链表逆序
    逆序原理:保留头节点下一个结点地址,将头节点断开,遍历除头节点以外的节点,将那些节点头插入头节点中。就能实习逆序。/********************************************************************* filename: demo2.c* author :lzj* date :2024/04/23* function:单向链......
  • VS2017+QT5.9.1 自定义loggerControl
    创建自定义类LoggerControl继承QListWidget#pragmaonce#include<QListWidget>#include"Helper.h"#include<QTime>#include<QPainter>classLoggerControl:publicQListWidget{Q_OBJECTpublic:LoggerControl(QWidget*paren......