一:题目
二:思路讲解
方法一:(双指针法)
我们采用的是双指针法,cur和prev,cur初识化为head,prev初始化为NULL。
两指针一前一后遍历整个链表,当cur遇到与val值节点的时候,我们就将其删除(此节点的前后节点相连接)
情况分为几种:
a:普通情况,val值节点不在第一个节点
第一步:初始状态:
第二步:找到与val值吻合的节点时候:
第三步: cur向后移动(curcur->next)
第四步: 然后再让prev指向cur(prev->next=cur)
这样就成功的删除了一个与val值吻合节点(本质是将val值节点的前后节点相连接)。
b:特殊情况,头删(val值节点处于第一个节点)
第一步:初始状态:
这种情况不能在进行遍历了,应该
解决方法:寻找一个新的头,也就是让上面的链表变成下面:
这样就变成了普通情况又可以按照之前的方法做下去了。
代码展示:
如果你想要有free的书写,可以这样:
由图可知: 判断特殊情况的if有两种写法,皆可。
方法二:
遍历原链表,把不是val的节点尾插到新链表。
1:首先需要三个指针
a:cur初始为head,cur用来遍历链表
b:newhead(NULL),此为最后返回的新的头指针
c:tail(NULL)
链表是一个空链表,直接返回newhead即可。
2:发现与val值吻合的节点,先用一个指针del去保存这个节点,然后直接让cur指向该节点的下一个节点,然后free掉该节点,(free(del))。
3:发现与val值 不 吻合的节点,就进行尾插,尾插有两种情况,一种是第一次尾插,一种是不是第一次尾插。
第一次尾插:tail为null,要将cur赋值给newhead和tail,赋值给newhead就让其指向了第一个尾插的节点,这样newhead就是新链表的头指针了,赋值给tail是因为,tail要指向新链表的尾节点,tail会与cur进行新的尾节点的插入等工作。
不是第一次尾插:即tail不为null,先尾插,让tail指向的节点去链接到新的尾插节点(tail->next=cur),再移动tail让tail去指向新的尾插节点(tail=tail->next)。
第一步:发现val值吻合的节点,先用一个指针del去保存这个节点,然后直接让cur指向该节点的下一个节点,然后free掉该节点,(free(del))。
第二步:发现与val值 不 吻合的节点的第一次尾插
tail为null,要将cur赋值给newhead和tail
第三步:不是第一次的尾插
即tail不为null,先尾插,让tail指向的节点去链接到新的尾插节点(tail->next=cur)
再移动tail,再让tail去指向新的尾插节点(tail=tail->next)。
代码展示:
注意:
尾插的最后一个节点的next没有置空,所以我们在最后将tail->next=NULL,但是在这之前,我们得先判断tail是否为空,因为可能这个链表是个空链表或者全为val,这样才能避免对tail(NULL)的解引用。这一步不能在尾插的else里面进行,因为tail和cur指向的同一个节点,你把tail的next置空,cur的next也置空了,cur无法往下进行遍历比较了, 所以在新链表完全形成之后,再去进行最为正确!