python删除递增有序链表结点 leetcode删除链表中的节点_空指针


思路一:不存在哨兵头结点时

该题为链表中数据的删除,即将符合条件的节点释放掉,将剩余节点重新连接起来,因为不只是将需要删除的节点释放掉。而且要将该节点的前后两个节点连接起来,因此不能单纯地找该节点,同时应该找前一个节点,按照以前的思路,定义一个指针pre,在cur依次向后判断的时候,跟随充当目标节点的前一个节点

python删除递增有序链表结点 leetcode删除链表中的节点_空指针_02


这样依次向后排查,直到cur指向空指针停止

但是忽略了一个问题,万一第一个节点就需要删除

python删除递增有序链表结点 leetcode删除链表中的节点_单链表_03


如图,若是第一个节点就需要删除,则将cur释放之后,在pre与next连接的过程中,因为pre此时是空指针,无法将next储存到pre当中去,此时就要另外考虑思路

当第一个节点需要删除,可以在该节点删除后把后一个节点当作头节点,再依次进行筛选

struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* pre=NULL;
struct ListNode* cur=head;
while(cur!=NULL)
{ 
     struct ListNode* next=cur->next;
    if(cur->val==val)
    {
       
        if(pre==NULL)//当第一个节点需要删除,改变头节点
        {
            free(cur);
            head=next;
            cur=next;
        }
        else
        {
     pre->next=next;
     free(cur);
     cur=next;
    }
    }
    else
    {
        pre=cur;
        cur=cur->next;
    }//如果不需要删除,则依次向后排查
}
return head;
}

注意:

1.因为最后要再次返回头节点,在头节点需要删除的这种情况下,记得把下一个节点传到head中

2.在利用指针的时候要注意函数的返回值类型,当函数是void类型的时候,对传进来的地址要进行改变,则需要二级指针,否则就是单纯的值传递,函数外无法改变,如果像本题要返回一个地址,这不需要二级指针

3.删除一个节点不是单纯地将前后两个节点连起来,要将该节点释放掉,然后指针cur指向下一个节点

思路二:含有哨兵头节点

因为要考虑第一个节点是否删除的问题,其实我们可以自己定义一个哨兵头节点,相当于链表加了一个首相,原先的头节点就变成了第二个,因此只需要依次向后排查即可

python删除递增有序链表结点 leetcode删除链表中的节点_python删除递增有序链表结点_04

struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* guardhead=(struct ListNode*)malloc(sizeof(struct ListNode));
guardhead->next=head;
struct ListNode* pre=NULL;
struct ListNode* cur=guardhead;
while(cur!=NULL)
{
    struct ListNode* next=cur->next;
    if(cur->val==val)
    {
        pre->next=next;
        free(cur);
        cur=next;
    }
    else
    {
        pre=cur;
        cur=cur->next;
    }
}
head=guardhead->next;
free(guardhead);
return head;
}

注意:
1.因为guardhead是新开辟出来的,最后返回的时候不能单纯地返回guardhead->next,否则会出现内存泄露的问题,最后要把guardhead释放掉
2.到最后连表示已经删除完了的,因此直接将guardhead->next赋给head即可