接上次单链表2
思路:
1.如果直接这样写
void SLtPopBack(SLT** pphead)
{
SLT* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
free(tail);
tail = NULL;
}
则tail指向的是最后一个结点,被释放后,其前面节点的next仍然指向他,并可访问到,会造成非法访问(起前面的结点将成为野指针-指向一块被释放的空间)
2.如果这样写
void SLtPopBack(SLT** pphead)
{
SLT* tail = *pphead;
SLT* prev = NULL;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
则删除时可以正常进行
but
如果删到最后一个
4个数据删4次,程序直接崩了
跟上面类似的情况
因为此处prev的下一个已经为空,-> 为解引用操作,又造成非法访问
so
3. 分三种情况
①直接为空
②有一个结点,第二个为空
③大于等于3结点
void SLtPopBack(SLT** pphead)
{
//1 .直接为空
assert(*pphead != NULL);
//2 .只有一个结点(第二个为空)
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//3 .结点 >= 3
else
{
SLT* tail = *pphead;
SLT* prev = NULL;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
同时,最后情况3可以这样写
SLT* tail = *pphead;
while (tail->next->next)
{
tail = tail->next;
}
free(tail->next);
tail->next = NULL;
不能上来就free掉plist,因为会找不到下一个
所以先保存头,并指向下一个地址
再free掉原来的头,再把原来的头指向刚保存的
void SLtPopFront(SLT** pphead)
{
assert(*pphead != NULL);
SLT* head = (*pphead)->next;
free(*pphead);
*pphead = head;
}
并要考虑到,若链表中无任何节点,*(pphead)->next,又对下一个地址解引用,又非法访问
所以要考虑是否有节点,加入assert / if
SLT* SListFind(SLT* phead, SLTDataType x)
{
SLT* cur = phead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
else
{
cur = cur->next;
}
}
return NULL;
}
找到之后,可以修改
pos = SListFind(plist, 33);
if (pos)
{
pos->data = 333;
}
如图,找到33后改为333
分2种情况:
①pos就在头部
此时,相当于头插,而且不能直接用插入,因为newnode->next永远不是pos(newnode)
②pos在其他任何地方
void SListInsert(SLT** pphead, SLT* pos, SLTDateType x)
{
SLT* newnode = CreatListNode(x);// 创建节点x
if (*pphead == pos)//如果pos等于头
{
//newnode->next = *pphead; // 直接把新节点的next存入原来的头
//*pphead = newnode; // 把新节点的地址放入作为新的头
SLtPushFront(pphead, x); // 头插
}
else
{
SLT* posPrev = *pphead;
while (posPrev->next != pos)
{
posPrev = posPrev->next;
}
posPrev->next = newnode;
newnode->next = pos;
}
}
创建节点,然后pos->next指向新节点的头,新节点的next指向原来pos的next
void SListInsertAfter(SLT* pos, SLTDateType x)
{
SLT* newnode = CreatListNode(x);
newnode->next = pos->next;
pos->next = newnode;
}