单向链表的初始化、插入、删除、遍历
/********************************************************************* file name: LnList.c
* author :MINDSETT@163.com
* date :2025/6/24
* function :实现一个单向不循环链表的接口,可实现链表的增删改查,另外为了提高可移植性,所以链表中
* 数据元素的类型为DataType_t,用户可以根据实际情况修改链表中元素的类型
* note :None
*
* CopyRight (c)2025MINDSETT@163.comAll 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);
}
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]