第一次尝试
删除链表中等于给定值 val 的所有节点。链表为无头结点、单向、不循环。(由于涉及到结构体,所以写不了完整的测试代码,下面展示的代码为 LeetCode 中写的代码)(LeetCode链接)
- 方法一:由于首元结点和非首元结点的删除不一样,所以情况讨论,如果要删除首元结点,只需先保留当前节点,然后将 head 指向下一个节点,再释放当前节点即可;如果要删除的不是首元结点,那么每次都要保留要删除节点的上一个节点 node 和要删除元素的下一个节点 next,然后释放掉当前节点,再让 node 指向 next,直至结束即可;
- 方法二:虚空大法,由于删除首元结点和非首元结点是不一样的,我们可以先创建一个虚首元结点,然后再把每个元素的删除当做非首元结点来看就行了,这样就可以将两种情况合二为一了,不过这样做的话,最终返回的就不是 head 了。而是 head -> next;
struct ListNode* removeElements(struct ListNode* head, int val){
//对头结点的筛选
while(head != NULL&&head->val == val){
struct ListNode* node=head;
//如果首节点等于val,那就将首指针向后移动,并释放首节点
head = head->next;
free(node);
}
//对非头结点的筛选
struct ListNode* node = head;
while(node != NULL&&node->next != NULL){
if(node->next->val == val){
struct ListNode* next = node->next;
struct ListNode* nextnext = next->next;
free(next);
node->next = nextnext;
}
else{
node=node->next;
}
}
return head;
//方法二:虚空大法
//创建一个虚节点,用来当做首元结点
struct ListNode _head;
//让虚首元结点指向现在的链表头结点,然后当做头结点
_head.next = head;
head = &_head;
struct ListNode* node=head;
//这样就可以将上面方法中的两种情况合二为一
while(node != NULL&&node->next != NULL){
if(node->next->val == val){
struct ListNode* next = node->next;
struct ListNode* nextnext = next->next;
free(next);
node->next = nextnext;
}
else{
node=node->next;
}
}
return head->next;
}