/********************************************************************************************************
* *
* FileName : LinkedList
* Author : madman_LX
* Contact me: 2912583505@qq.com
* Date : 2024/04/22
* Function : 单向链表的遍历,插入和删除
* Note : None
*
* Function List:
* Version : 2.0
* History : madman_LX 24/04/23 2.0 增加了指定插入的比较数据方法
madman_LX 24/04/22 1.0 none
* 《历史修改记录) <author> <time> <version > <desc>
* Copyright (c) 2023-2024 All right Reserved
* ******************************************************************************************************/
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//指的是单向链表中的结点有效数据类型,用户可以根据需要进行修改
typedef int DataType_t;
//构造链表的结点,链表中所有结点的数据类型应该是相同的
typedef struct LinkedList
{
DataType_t data; //结点的数据域
struct LinkedList *next; //结点的指针域
}LList_t;
//创建一个空链表,空链表应该有一个头结点,对链表进行初始化
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_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;
}
//头插
void 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;
}
//2.判断链表是否为空,如果为空,则直接插入即可
if (NULL == Head->next)
{
Head->next = New;
return;
}
//3.如果链表为非空,则把新结点插入到链表的头部
New->next = Head->next;
Head->next = New;
return;
}
//尾插
void LList_TailInsert(LList_t *Head,DataType_t data)
{
//创建以一个新的节点,并对新节点进行初始化
LList_t *New = LList_NewNode(data);
if (NULL == New)
{
printf("can not insert new node\n");
}
//2.判断链表是否为空,如果为空,则直接插入即可
if (NULL == Head->next)
{
Head->next = New;
}
//3.如果链表为非空,则把新结点插入到链表的尾部
LList_t *Per = Head;//备份头节点的地址
while( Per->next )//while循环寻找尾节点
{
Per = Per->next;
}
New->next = NULL;//在尾部插入新的节点
Per->next = New;
}
//指定插
bool LList_DestInsert(LList_t *Head,DataType_t dest,DataType_t data)
{ //创建以一个新的节点,并对新节点进行初始化
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.如果链表为非空,则把新结点指定插入到链表指定位置
LList_t *Per = Head;//备份头节点的地址
int p = 1;//定义一个变量记录指定链表的位置,找到指定位置后,向指定位置后面插入数据。
while(p != dest)
{
Per = Per->next;
p++;
}
New->next = Per->next;
Per->next = New ;
//.如果链表为非空,则遍历列表,找到目标节点,比较目标节点数据域
// LList_t *Per = Head->next;
// while(Per != NULL && destval != Per->date )
// {
// Per = Per->next;
// }
// if(Per == NULL)
// {
// return false;
// }
// New->next = Per->next;
// Per->next = New ;
return true;
}
//头删
bool LList_HeadDel(LList_t *Head)
{
//2.判断链表是否为空,如果为空,则无需删除
if (NULL == Head->next)
{
return false;
}
//3.如果链表为非空,则把链表首节点删除
LList_t *Per = Head;//备份头节点的地址
LList_t *p = Per->next;//定义一个变量p记录首节点的地址
Per->next = p->next;
p->next = NULL;
free(p);
return true;
}
//尾删
bool LList_TailDel(LList_t *Head)
{
//2.判断链表是否为空,如果为空,则无需删除
if (NULL == Head->next)
{
return false;
}
//3.如果链表为非空,则把链表尾节点删除
LList_t *Per = Head;//备份头节点的地址
LList_t *p = Head->next;//定义一个变量记录首节点的地址
while( p->next != NULL)//while循环寻找尾节点
{
p = p->next;
Per = Per->next;
}
Per->next = NULL;//删除尾节点
free(p);
return true;
}
//指定删
bool LList_DestDel(LList_t *Head,DataType_t dest)
{
//2.判断链表是否为空,如果为空,则无需删除
if (NULL == Head->next)
{
return false;
}
//3.如果链表为非空,则把链表头节点删除
LList_t *Per = Head;//备份头节点的地址
LList_t *p = Head->next;//记录首节点的地址
int i=1;//定义一个变量记录节点位置
while(i != dest)//while循环找到指定删除位置
{
p = p->next;
Per = Per->next;
i++;
}
Per->next = p->next;
p->next = NULL;
free(p);
return true;
}
//遍历
void LList_Print(LList_t *Head)
{
//对链表的头文件的地址进行备份
LList_t *Phead = Head;
//首结点
while(Phead->next)
{
//把头的直接后继作为新的头结点
Phead = Phead->next;
//输出头结点的直接后继的数据域
printf("data = %d\n",Phead->data);
}
}
int main(int argc, char const *argv[])
{
//创建一个新的链表
LList_t *Head = LList_Create();
//头插插入数据
LList_HeadInsert(Head,10);
LList_HeadInsert(Head,20);
LList_HeadInsert(Head,30);
LList_HeadInsert(Head,40);
LList_Print(Head);
printf("\n");
//尾插
LList_TailInsert(Head,50);
LList_Print(Head);
printf("\n");
//指定插
LList_DestInsert(Head,2,45);
LList_Print(Head);
printf("\n");
//头删
LList_HeadDel(Head);
LList_Print(Head);
printf("\n");
//尾删
LList_TailDel(Head);
LList_Print(Head);
printf("\n");
//指定删
LList_DestDel(Head,4);
LList_Print(Head);
printf("\n");
return 0;
}