单链表的尾插和尾删都需要先找到链表的尾部再进行操作
链表的尾插
//尾插
void SListPushBack(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
// 新建节点
SLTNode* newNode = BuyListNode(x);
// 链表为空
if (*pphead == NULL)
{
*pphead = newNode;
}
else
{
// 找到尾部
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
// 插入尾部
tail->next = newNode;
}
}
我们仍可以先用assert断言一下传来的参数(一个好的习惯),在插入前,需先建一个新的节点,
因为对于空链表和非空链表的尾插有些区别,所以我们要做一判断链表是否为空
若链表为空,则直接将新节点接入头指针;
若链表为非空,则需要我们先遍历链表,找到尾节点(这里可以用一个tail指针来找),最后将新节点接入尾部tail的next。
链表的尾删:
//尾删
void SListPopBack(SLTNode** pphead)
{
assert(pphead);
//温柔判断是否剩下最后一个节点
//if (*pphead == NULL)
//{
// return;
//}
//暴力判断是否剩下最后一个节点
assert(*pphead != NULL);
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
SLTNode* prev = NULL;
SLTNode* tail = *pphead;
while (tail->next) //等同于 while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
prev->next = NULL;
free(tail);
tail = NULL;
}
}
同链表的尾插一样 ,对于只有一个节点的链表和有多个节点的链表来说,有些区别,因此我们需要进行讨论
若链表只有一个节点,那我们直接用free释放*pphead即可,再将*pphead指向空指针(防止其成为野指针)
若链表有多个节点,我们便需要先找到尾节点,因为在最后我们需要将新的尾结点的next指向空指针(防止指向野指针),我们还需要知道原尾节点的上一个节点,因此,我们可以用两个指针prev和tail来完成,在遍历链表中,先将tail赋给prev,tail再向后移一个节点。最后将tail尾部free掉,并将prev->next指向空。