每日一题(移除链表元素)
思路一:
可以创建一个新的链表头节点newhead,只要是原链表中值不为val的节点、都通过尾插操作插到newhead所指向的链表中,原链表中值为val的节点直接删除释放掉。为了让尾插操作更方便,还需要再定义一个tail指针,用于记录newhead链表中的最后一个元素的地址。(所以每次尾插之后tail指针要进行更新)newhead保持不变,永远指向第一个节点。所以共要,创建四个结构体指针:cur、newhead、next、tail。cur指针用于遍历原链表,newhead用于记录新链表的头,最后函数的返回值就用newhead进行返回,next指针用于记录cur指针的下一个位置,方便进行尾插操作,tail指针用于记录newhead链表中的最后一个元素,并且每一次的尾插之后都要进行更新。
思路二:
直接使用cur指针和prev指针遍历原链表,cur指针从原链表的头开始遍历,prev用于记录cur的上一个节点的地址。假如cur指向的节点的值为val,先让prev和cur节点的next连接起来。接着释放cur指向的节点。(但是假如cur一开始指向head时,该节点的值也恰好为val,则此时要进行头删操作,并且释放之后的节点无效了,需要更新head。)
思路一代码:
struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode* cur = head; struct ListNode* next = head; struct ListNode* newhead = NULL; struct ListNode* tail = newhead; while(cur) { //满足删除条件 if(cur ->val != val) { //假如newnode是空 if(newhead== NULL) { next = cur->next; newhead = cur; tail = newhead; cur = next; } //newnode不是空 else { next = cur->next; tail->next = cur; tail = tail->next; cur = next; } } //不满足删除条件 else { next = cur->next; free(cur); cur = next; } } if(tail!=NULL) tail->next = NULL; return newhead; }
思路二代码:
struct ListNode* removeElements(struct ListNode* head, int val){ struct ListNode* prev=NULL; struct ListNode* cur = head; while(cur) { //节点的值满足删除条件 if(cur->val == val) { //当删除的是头节点 if(cur == head) { head = cur->next; free(cur); cur = head; } //当删除的不是头节点 else { prev->next = cur->next; free(cur); cur = prev->next; } } //节点的值不满足删除条件 else//向后走 { prev = cur; cur=cur->next; } } return head; }
注意:以下都是针对思路一的讲解:
图解:
在代码的初始状态是如下图所示的:此时的next和cur都指向head,也就是原链表中的第一个元素。newhead和tail为空指针时,要进行特判,记录cur的下一个位置之后,要先让newhead指向cur,同时tail指针也向后移动了一步指向cur,完成了更新。
当来到下图所示的常规情况时,此时的tail和newhead都不为空,newhead不能动,记录cur的next之后,直接改变tail的next并且更新tail即可。
当代码进行到如下图所示时,此时cur为空指针,while循环结束,按常理来讲就应该要返回newhead了。(单链表的最后一个节点的next指针的值必须是NULL)但是,此时的的tail的next指针仍然是指向6所在的节点的,并且该节点虽然被释放了,但是值就会变成随机值,并不一定是NULL,所以在返回newhead之前,要将tail的next置为空指针。
注意:当测试用例使用空链表测试时,cur的值也为NULL,while循环并没有进入。也就说明tail的值一直都是NULL并没有被改变,如果此时仍然使用tail->next = NULL;强行置空就会出现空指针访问错误。所以此处需要进行特判。
完结
本题的全部分析就到这里啦,若有不足,欢迎评论区指正,下期见!