文章目录
一、链表的概念
链表是一种物理存储结构上非连续、非顺序的存储结构,但链表在逻辑上是连续的,顺序的,而数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
二、链表的基本实现
1、初始化`
其中SL是链表的缩写
typedef int SLTDateType;
typedef struct SListNode
{
SLTDateType Date;
SListNode* next;
}SListNode;
2、节点的创建 SLTBuyNode
此处节点的创建为了接下来的增加节点铺垫
SLTNode*SLTBuyNode(SLTDataType x)//创建一个新的节点,节点后接空指针
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
return newnode;
}
3、节点打印SLTPrint
方便后面的调试,
1,同时这里只是传一级指针因为单链表是连续的可以直接找到并打印,
2,下面会传二级指针因为下面会修改链表,高一级指针才可以将修改后的值传回去
void SLTPrint(SLTNode* phead) {
SLTNode* pcur = phead;
while (pcur)
{
printf("%d->", pcur->data);
pcur = pcur->next;
}
printf("NULL\n");
}
4、头插SLTPushFront
1,创造一个节点newNode
2,把新节点下一位接到原节点*pphead开头
3、将开头节点提前到newNode
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
SLTNode* newnode = SLTBuyNode(x);
newnode->next = *pphead;//将空指针介入
*pphead = newnode;//定义头指针
}
5、尾插SLTPushBack
两种情况
1、插空
2、非空,其中ptail是找尾节点的,有一个易错点,必须将头节点赋给一个节点ptail,来遍历,不然的话直接用头结点,头结点会不断覆盖
void SLTPushBack(SLTNode**pphead, SLTDataType x)
{
assert(pphead);
SLTNode*newnode=SLTBuyNode(x);
//链表为空
if (*pphead == NULL)
{
*pphead = newnode;
return;
}
//链表不为空
SLTNode* ptail = *pphead;//易错点
while (ptail->next)
{
ptail = ptail->next;//依次交换
}
ptail->next = newnode;//插入尾指针
}
6、头删SLTPopFront
void SLTPopFront(SLTNode** pphead)
{
assert(pphead);
SLTNode* ptail = *pphead;
*pphead = (*pphead)->next;//把头节点赋给第二个节点
free(ptail);
ptail = NULL;
}
7、尾插SLTPopBack
分为两种情况
1.只有一个节点
2,大于两个节点,只有一点找不到倒数第二个节点,所以有prev=ptail,来找到现在最后一个节点
void SLTPopBack(SLTNode** pphead)
{
assert(pphead);
assert(*pphead);
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
return;
}
SLTNode* ptail = *pphead;
SLTNode* prev = NULL;
while (ptail->next)
{
prev = ptail;
ptail = ptail->next;
}
prev->next = NULL;
free(ptail);
ptail = NULL;
}
8、找节点SLTFind
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
SLTNode* pcur = *pphead;
while (pcur->next)
{
if (pcur->data == x)
{
return pcur;
}
pcur = pcur->next;
}
return NULL;
}
9、插pos前面SLTInsert
头插
下面是一个错误示范
目的是理解其中二级指针,一级指针的含义,这么写是错的,SLTPushBack里得参数
是二级指针,二级指针才能改变一级指针,但prev是一级指针
一级指针
SLTNode* prev = *pphead;
if (prev == pos)
{
SLTPushFront(&prev, x);
return;
}
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
assert(pphead);
assert(pos);//节点存在
assert(*pphead);
SLTNode* newnode = SLTBuyNode(x);
//下面是修改
if (*pphead == pos)
{
SLTPushFront(pphead, x);
return;
}
SLTNode* prev = *pphead;
while (prev->next!= pos)
{
prev = prev->next;
} prev->next = newnode;
newnode->next = pos;
}
10、插pos后面SLTInsertAfter
void SLTInsertAfter(SLTNode* pphead, SLTNode* pos, SLTDataType x)
{
SLTNode* newnode = SLTBuyNode(x);
newnode->next = pos->next;
pos->next = newnode;
//易错下面是错误写法
// pos->next=newnode;
//newnode->pos->next;
}
销毁节点11.SLTDesNode
void SLTDestroy(SLTNode**pphead)
{
assert(pphead);
assert(*pphead);
SLTNode* pcur = *pphead;
while (pcur)
{
SLTNode* next = pcur->next;
free(pcur);
pcur = next;
}
*pphead = NULL;
}
创作不易,希望点赞