剑指offer---018(删除链表的节点)

更多题目可点链接:《 剑指offer》 目录索引


题目一

给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。

思路:

  • 时间复杂度为O(1),如果删除的非尾节点,采用替换法删除

  • 如果是尾节点,采用一般删除

替换法删除的图解:https://blog.csdn.net/zhangye3017/article/details/78933001

代码:

#include<iostream>
using namespace std;

typedef int DataType;

typedef struct SListNode
{
    DataType _data;
    struct SListNode* _next;
}SListNode;


SListNode* BuyNode(DataType x)
{
    SListNode* node = (SListNode*)malloc(sizeof(SListNode));
    if (node != NULL)
    {
        node->_data = x;
        node->_next = NULL;
    }

    return node;
}

void  SListPushBack(SListNode** ppHead, DataType x)
{
    SListNode* node = BuyNode(x);
    if (*ppHead == NULL)
    {
        *ppHead = node;
    }
    else
    {
        SListNode* tail = *ppHead;
        while (tail->_next)
        {
            tail = tail->_next;
        }

        tail->_next = node;
    }


}

SListNode* FindNode(SListNode* list,DataType x)
{
    SListNode* cur = list;
    while (cur)
    {
        if (cur->_data == x)
        {
            return cur;
        }
    }
    return NULL;
}

void SListPrint(SListNode* pHead)
{
    SListNode* cur = pHead;
    while (cur)
    {
        printf("%d ", cur->_data);
        cur = cur->_next;
    }
    printf("\n");

}

void DeleteNode(SListNode** pListHead, SListNode* pToBeDeleted)
{
    if (*pListHead == NULL || pToBeDeleted == NULL)
        return;


    if (pToBeDeleted->_next == NULL && *pListHead==pToBeDeleted)
    {
        //尾节点,且只有一个节点

        free(*pListHead);
        *pListHead = NULL;
    }
    else  if (pToBeDeleted->_next==NULL)
    {
        //尾节点,且多个节点

        SListNode* cur = *pListHead;
        while (cur->_next != pToBeDeleted)
        {
            cur = cur->_next;
        }

        cur->_next = NULL;


        free(pToBeDeleted);
        pToBeDeleted = NULL;

    }
    else
    {
        //不是尾节点

        SListNode* next = pToBeDeleted->_next;
        pToBeDeleted->_data = next->_data;

        pToBeDeleted->_next = next->_next;

        free(next);
        next = NULL;
    }

}


void Test()
{
    SListNode* list = NULL;
    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPushBack(&list, 4);
    SListPushBack(&list, 5);
    SListPushBack(&list, 6);
    SListPushBack(&list, 7);

    SListPrint(list);


    DeleteNode(&list, FindNode(list, 1));
    DeleteNode(&list, FindNode(list, 2));
    DeleteNode(&list, FindNode(list, 3));
    DeleteNode(&list, FindNode(list, 4));
    DeleteNode(&list, FindNode(list, 5));
    DeleteNode(&list, FindNode(list, 6));
    DeleteNode(&list, FindNode(list, 7));
    DeleteNode(&list, FindNode(list, -1));

    SListPrint(list);
}

int main()
{
    Test();
    system("pause");
    return 0;
}

题目二

在一个排序的链表中,如何删除重复的结点?例如:1,2,2,3,4,4,5,6 删除重复节点后为1,2,3,4,5,6

思路:

  • 题目给出链表是有序的,故如果有重复的节点,一定是在当前节点的下一个

  • 这里没有时间复杂度要求,可以采用常规删除法删除重复的节点

代码:

#include<iostream>
using namespace std;

typedef int DataType;
typedef struct SListNode
{
    DataType _data;
    struct SListNode* _next;
}SListNode;


SListNode* BuyNode(DataType x)
{
    SListNode* node = (SListNode*)malloc(sizeof(SListNode));
    if (node != NULL)
    {
        node->_data = x;
        node->_next = NULL;
    }

    return node;
}

void  SListPushBack(SListNode** ppHead, DataType x)
{
    SListNode* node = BuyNode(x);
    if (*ppHead == NULL)
    {
        *ppHead = node;
    }
    else
    {
        SListNode* tail = *ppHead;
        while (tail->_next)
        {
            tail = tail->_next;
        }

        tail->_next = node;
    }


}

SListNode* FindNode(SListNode* list, DataType x)
{
    SListNode* cur = list;
    while (cur)
    {
        if (cur->_data == x)
        {
            return cur;
        }
    }
    return NULL;
}

void SListPrint(SListNode* pHead)
{
    SListNode* cur = pHead;
    while (cur)
    {
        printf("%d ", cur->_data);
        cur = cur->_next;
    }
    printf("\n");

}



void DeleteDuplication(SListNode** pHead)
{
    if (pHead == NULL || *pHead == NULL)
        return;

    SListNode* cur = *pHead;

    SListNode* deletenode = NULL;

    while (cur)
    {
        SListNode* next = cur->_next;
        if (next!=NULL  && cur->_data == next->_data)
        {
            //既然是排序过的链表,如果有重复的,必定重复的是当前节点的下一个
            deletenode = next;
        }

        if (deletenode != NULL)
        {
            cur->_next = next->_next;
            free(deletenode);
            deletenode = NULL;
        }
        cur = cur->_next;   

    }


}

void Test()
{
    //两个重复
    SListNode* list = NULL;
    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 2);
    SListPushBack(&list, 4);
    SListPushBack(&list, 5);
    SListPushBack(&list, 6);
    SListPushBack(&list, 6);
    DeleteDuplication(&list);
    DeleteDuplication(&list);
    SListPrint(list);


    //没有重复
    SListNode* list1 = NULL;
    SListPushBack(&list1, 0);
    SListPushBack(&list1, 2);
    SListPushBack(&list1, 3);
    SListPushBack(&list1, 4);
    SListPushBack(&list1, 5);
    SListPushBack(&list1, 6);
    SListPushBack(&list1, 7);

    DeleteDuplication(&list1);
    DeleteDuplication(&list1);
    DeleteDuplication(&list1);
    DeleteDuplication(&list1);
    DeleteDuplication(&list1);
    DeleteDuplication(&list1);
    DeleteDuplication(&list1);
    DeleteDuplication(&list1);
    DeleteDuplication(&list1);


    SListPrint(list1);


    //只有一个不一样
    SListNode* list2 = NULL;
    SListPushBack(&list2, 1);
    SListPushBack(&list2, 1);
    SListPushBack(&list2, 1);
    SListPushBack(&list2, 1);
    SListPushBack(&list2, 1);
    SListPushBack(&list2, 1);
    SListPushBack(&list2, 2);

    DeleteDuplication(&list2);
    DeleteDuplication(&list2);
    DeleteDuplication(&list2);
    DeleteDuplication(&list2);
    DeleteDuplication(&list2);
    DeleteDuplication(&list2);
    DeleteDuplication(&list2);
    DeleteDuplication(&list2);
    DeleteDuplication(&list2);


    SListPrint(list2);



    //全重复
    SListNode* list3 = NULL;
    SListPushBack(&list3, 1);
    SListPushBack(&list3, 1);
    SListPushBack(&list3, 1);
    SListPushBack(&list3, 1);
    SListPushBack(&list3, 1);
    SListPushBack(&list3, 1);
    SListPushBack(&list3, 1);

    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    DeleteDuplication(&list3);
    SListPrint(list3);
}

int main()
{
    Test();
    system("pause");
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值