[C题目]力扣203. 移除链表元素

203. 移除链表元素 - 力扣(LeetCode)

 方法一:删除val值的结点,并将其前后的结点连接上。

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* prev = NULL;//prev标记cur前一个结点的位置
    struct ListNode* cur = head;//cur表示当前要检查的结点
    while (cur)//对链表进行遍历,结点不为NULL就检查其val值。
    {
        if(cur->val==val)//val值与val相等
        {
            if(cur==head)//头删,注意最后是要返回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;
}

 方法二:旧链表按顺序逐个遍历,把不是val值的结点尾插到一个新的链表

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* cur=head;//cur表示当前检查的结点
    struct ListNode* tail=NULL;//tail表示新链表的尾结点
    while(cur)//当前结点cur不为空就检查其val值
    {
        if(cur->val==val)//需要删除结点的情况
        {
            if(cur==head)//头删
            {
                head=head->next;//将头结点的位置改成下一个结点的位置
            }
            struct ListNode* tmp=cur->next;//保存下一个结点位置
            free(cur);//释放当前结点
            cur=tmp;//挪到下一个结点
        }
        else//赋值到新链表的情况
        {
            if(cur==head)//在新的链表中尾插第一个结点,因为最后面是返回head,所以这里只需布置好tail和cur的位置,不需要对head进行处理。
            {
                tail=head;
                cur=cur->next;
            }
            else//在新链表中尾插除头结点以外的结点
            {
                tail->next=cur;//连接新结点
                cur=cur->next;//挪动cur到旧链表的下一位
                tail=tail->next;//挪动tail到新链表的下一位
            }
        }
    }
    if(head!=NULL)//如果head为NULL,那么前面的while循环不会进入,tail依然是空。所以不需要对tail->next进行置空,最后直接返回head即可。
        tail->next=NULL;//tail->next需要置空,因为可能存在旧链表最后一个结点内容被删除(释放)的情况,所以tail->不会被新结点的地址覆盖,置空防止非法访问内存。
    return head;
}

方法二(变形):创建一个哨兵位的头结点,起带头作用,在挪动结点的时候不会因为head的存在而显得麻烦。

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* cur=head;//cur表示当前检查的结点
    struct ListNode* tail=NULL;//tail表示新链表的尾结点
    
    head=tail=(struct ListNode*)malloc(sizeof(struct ListNode));//哨兵位的头结点
    head->next=NULL;//以防出现一开始就是空链表的情况,后面有个head=head->next;

    while(cur)//当前旧链表中结点cur不为空就检查其val值
    {
        if(cur->val==val)//需要删除旧链表结点的情况
        {
            struct ListNode* del=cur;
            cur=cur->next;
            free(del);
        }
        else//赋值到新链表的情况
        {
            tail->next=cur;
            tail=tail->next;
            cur=cur->next;
        }
    }
    struct ListNode* del=head;//保存哨兵位头结点,后面用于释放。
    head=head->next;
    free(del);
    if(head!=NULL)//防止出现旧链表最后一个结点会被删除,新链表的tail->next变成野指针的情况。
        tail->next=NULL;
    return head;
}

你可能感兴趣的:(链表,leetcode,c语言)