-------------先看题目-----------
-------------简略画图-----------
当我们看到一个关于数据结构的题并且读完题目时,最最重要的就是能够具有画图能力把脑海中的思维来复现在所画的图上,这样不仅可以使自己培养一个良好的习惯,并且可以使得自己思路清晰能够稳中求胜及错误复查。而数据结果则更需要我们对于指针的理解以及空间上的划分能够熟练,而画图这是确保实现这个目的的重要因素。因此依题意我们做出草图如下
-------------着手分析-----------
已知题意的大概内容简要理解就是,给一个链表找出数字val并删除,然后返回链表。所以我们自然而然就会想到需要去用一个指针来指向所有的数据来帮助我们判断,而我们所返回的又应该也是头指针并且还要为了保护数据的作用,于是我们设置如下三个指针如图所示,先让新设置的两个指针置空下面会提到用处。
所以我们的基本步骤就是,把删除完出现val的链表用新的头指针以及尾指针表示并且在原有链表上加以改造,这样子的好处是节省空间,该空间复杂度为O(1),因为链表只找一次所以时间复杂度为O(n)。
-------------具体思路-----------
我们假设val的值为6,所以我们通过cur = cur -> next的步骤使得让cur指针往链表中走来判断每个结构体中的val是不是我们要寻找的val的值,如果是则删除如果不是则跳过判断下一个,假设开头的第一个不是,那就让我们的tail和newhead指针只向头节点,如图所示。
然后在这个时候肯定就有聪明的老铁就提出来:“不是哥们,你这也太想当然了吧,万一val值在第一个怎么办?”别急,小生为了帮助您理解就此为您献上步骤图及代码
可能有些新手朋友看到需要删除就库库(拟声)写下free(cur)的代码,其实这是错误的需要避免,设置一个新指针del指向要被删除的结构体del是因为free掉cur的同时结构体指针*next也会free掉就会导致cur = cur ->next 这步找不到下一个结构体。所以就用del保存删除del就好啦。代码附上
-------------具体代码-----------
if (cur->date == date)
{
SLTNode* del = cur;
cur = cur->next;
free(del);
}
然后我们就把cur指向下一个结构体重复判断 ,想必聪明的彦祖们应该也想到了这需要一个循环来实现,哪到哪一步就可以停下来呢,当然就是当cur指向最后一个结构体为止。完整代码如下
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* cur = head ;
struct ListNode*newhead = NULL , *tail = NULL;
while(cur)
{
if(cur->val == val)
{
struct ListNode* del = cur;
cur = cur -> next;
free(del);
}
else
{
if((newhead &&tail) ==NULL)
{
newhead = tail = cur;
}
else
{
tail ->next = cur;//ps:1
tail = tail -> next;
}
cur = cur -> next;
}
}
if(tail) //ps:2
tail -> next = NULL;
return newhead;
}
-------------需要警惕-----------
这里有两点ps1和ps2两个地方需要给各位彦祖们解释一下,ps1这个标记呢顾名思义就是使得尾指针指向的结构体的next指针指向cur,有彦祖就想当然了这一步不是理所应当吗为什么还要多此一举来说明,话不多说如图所示(为方便观察只展示重要部分)
tail后面的结构体以及被free如果还是按往常一样tail = tail -> next则直接报错,因为tail表示也妹瞅着人呀 它不知道该指到哪里更不会想当然的指到我们以为的cur位置。所以需要ps1这个地方来给tail指针定个位。
而ps2则是所有彦祖们中最容易忽略并且是最为关键的内容那就是置空,判断一个链表结束的标志那就是尾结点的next指向的是NULL哦,以上就是全部内容。数据结构一画图二分析乃是重中之重。如有疑问可在评论区留言,大家一起学习一起进步。