- /********************************************************************
- * file name: LnList.c
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * function : 实现一个单向不循环链表的接口,可实现链表的增删改查,另外为了提高可移植性,所以链表中
- * 数据元素的类型为DataType_t,用户可以根据实际情况修改链表中元素的类型
- * note : None
- *
- * CopyRight (c) 2025 MINDSETT@163.com All Right Reserved
- ********************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- //指定链表中元素的数据类型,用户可根据需要进行修改
- typedef int DataType_t;
- //构造链表的结点,链表中所有结点的数据类型应该是相同的(数据域+指针域)
- typedef struct SingleLinkedList
- {
- DataType_t data; //结点的数据域
- struct SingleLinkedList * next; //结点的指针域
- }LnList_t;
- /********************************************************************
- * name : Seqlist_Creat
- * function : 创建一个空链表,空链表应该有一个头节点,对链表进行初始化
- * argument : None
- * retval : 返回头结点的地址
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- LnList_t *LnList_Create(void)
- {
- //创建一个头结点并对头结点申请内存
- LnList_t* Head=(LnList_t*)calloc(1,sizeof(LnList_t));
- if (NULL==Head){
- perror("calloc memory for Head is failed\n");
- exit(-1);
- }
- //对头结点进行初始化
- Head->next=NULL;
- //将头结点的地址返回
- return Head;
- }
- /********************************************************************
- * name : LnList_NewNode
- * function : 创建一个新结点,并为新结点申请堆内存以及对新结点的数据域和指针域进行初始化
- * argument :
- * @data:新结点的数据
- * retval : 返回新结点的地址
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- LnList_t * LnList_NewNode(DataType_t data)
- {
- //创建新结点,并未新结点申请堆内存
- LnList_t * New=(LnList_t*)calloc(1,sizeof(LnList_t));
- if (NULL==New){
- perror("calloc memory for NewNode is failed\n");
- return NULL;
- }
- //对新结点的数据域和指针域进行初始化
- New->data=data;
- New->next=NULL;
- return New;
- }
- /********************************************************************
- * name : LnList_FirstInsert
- * function : 创建一个新结点,并把新结点插入链表的首部
- * argument :
- * @Head:插入的链表
- * @data:新结点的数据
- * retval : 成功返回true,失败返回false
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- bool LnList_FirstInsert(LnList_t * Head,DataType_t data)
- {
- //创建新结点,并对新结点进行初始化
- LnList_t* New=LnList_NewNode(data);
- if (NULL==New){
- perror("Create New node is failed\n");
- return false;
- }
- //判断链表是否为空,如果为空,则将新结点直接插入
- if (NULL==Head->next){
- Head->next=New;
- return true;
- }
- //如果链表为非空,则将新结点插入链表的首部
- New->next=Head->next;
- Head->next=New;
- return true;
- }
- /********************************************************************
- * name : LnList_TailInsert
- * function : 创建一个新结点,并把新结点插入链表的尾部
- * argument :
- * @Head:插入的链表
- * @data:新结点的数据
- * retval : 成功返回true,失败返回false
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- bool LnList_TailInsert(LnList_t * Head,DataType_t data)
- {
- //创建新结点,并对新结点进行初始化
- LnList_t* New=LnList_NewNode(data);
- if (NULL==New){
- perror("Create New node is failed\n");
- return false;
- }
- //判断链表是否为空,如果为空,则将新结点直接插入
- if (NULL==Head->next){
- Head->next=New;
- return true;
- }
- //如果链表为非空,则链表的头结点的地址进行备份,循环找到链表的尾部,并将新结点插入链表的尾部
- LnList_t *Phead=Head;
- while(Phead->next){
- Phead=Phead->next;
- }
- Phead->next=New;
- return true;
- }
- /********************************************************************
- * name : LnList_DestInsert
- * function : 创建一个新结点,并把新结点插入链表的指定位置
- * argument :
- * @Head:插入的链表
- * @Dest:指定需要新结点插入位置的直接前驱的数据
- * @data:新结点的数据
- * retval : 成功返回true,失败返回false
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- bool LnList_DestInsert(LnList_t * Head,DataType_t Dest,DataType_t data)
- {
- //创建新结点,并对新结点进行初始化
- LnList_t* New=LnList_NewNode(data);
- if (NULL==New){
- perror("Create New node is failed\n");
- return false;
- }
- //判断链表是否为空,如果为空,则将新结点直接插入
- if (NULL==Head->next){
- Head->next=New;
- return true;
- }
- //如果链表为非空,遍历链表,目的是找到目标结点,比较结点的数据域
- LnList_t *Phead=Head->next;
- while(Phead!=NULL && Dest!=Phead->data){
- Phead=Phead->next;
- }
- if(NULL==Phead){
- printf("Dest is not found\n");
- return false;
- }
- //找到目标结点,则把新结点加入到目标结点的后面
- New->next=Phead->next;
- Phead->next=New;
- return true;
- }
- /********************************************************************
- * name : LnList_FirstDel
- * function : 删除链表的首结点
- * argument :
- * @Head:链表的头结点
- * retval : 成功返回true,失败返回false
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- bool LnList_FirstDel(LnList_t* Head)
- {
- //判断链表是否为空
- if (NULL==Head || NULL==Head->next){
- perror("Linked list is empty\n");
- return false;
- }
- //备份链表的头结点和首结点
- LnList_t* Pfirst=Head->next;
- //将头结点的指针域指向首结点的指针域
- Head->next=Pfirst->next;
- //释放首结点占用的内存
- Pfirst->next=NULL;
- free(Pfirst);
- return true;
- }
- /********************************************************************
- * name : LnList_TailDel
- * function : 删除链表的尾结点
- * argument :
- * @Head:链表的头结点
- * retval : 成功返回true,失败返回false
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- bool LnList_TailDel(LnList_t* Head)
- {
- //判断链表是否为空
- if (NULL==Head || NULL==Head->next){
- perror("Linked list is empty\n");
- return false;
- }
- //备份链表的头结点和首结点
- LnList_t* Phead=Head;
- LnList_t* Pfirst=Phead->next;
- //循环找到链表的尾结点和尾结点的直接前驱
- while(Pfirst->next){
- Pfirst=Pfirst->next;
- Phead=Phead->next;
- }
- //将尾结点的直接前驱的指针域指向为NULL
- Phead->next=NULL;
- //释放尾结点占用的内存
- free(Pfirst);
- return true;
- }
- /********************************************************************
- * name : LnList_DestDel
- * function : 删除链表的指定结点
- * argument :
- * @Head:链表的头结点
- * @Dest:需要删除的指定结点
- * retval : 成功返回true,失败返回false
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- bool LnList_DestDel(LnList_t* Head,DataType_t Dest)
- {
- //判断链表是否为空
- if (NULL==Head || NULL==Head->next){
- perror("Linked list is empty\n");
- return false;
- }
- //Phead指向前驱,Pfirst指向当前结点
- LnList_t* Phead=Head;
- LnList_t* Pfirst=Phead->next;
- //遍历链表,目的是找到目标结点,比较结点的数据域
- while(Pfirst!=NULL && Dest!=Pfirst->data){
- Phead=Pfirst;
- Pfirst=Pfirst->next;
- }
- if(NULL==Pfirst){
- printf("Dest is not found\n");
- return false;
- }
- //删除目标结点——将指定结点的直接前驱的指针域指向指定结点的直接后继
- Phead->next=Pfirst->next;
- //释放指定结点占用的内存
- Pfirst->next=NULL;
- free(Pfirst);
- return true;
- }
- /********************************************************************
- * name : LnList_Print
- * function : 遍历输出链表中各个结点的数据
- * argument :
- * @Head:需要遍历的链表
- * retval : None
- * author : MINDSETT@163.com
- * date : 2025/6/24
- * note : None
- *
- * ******************************************************************/
- void LnList_Print(LnList_t* Head)
- {
- //判断链表是否为空
- if (NULL==Head || NULL==Head->next){
- perror("Linked list is empty\n");
- return ;
- }
- //对链表的头节点的地址进行备份
- LnList_t *Phead=Head;
- //循环遍历链表
- while(Phead->next){
- //把头结点的直接后继作为新的头结点
- Phead= Phead->next;
- //输出头结点的直接后继的数据域
- printf("Data=%d\n",Phead->data);
- }
- }
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |