在O(1)时间删除链表结点

在O(1)时间删除链表结点

问题描述:
给定单向链表的头指针和一个结点指针;定义一个函数在O(1)时间删除链表结点。链表结点与函数的定义如下:

struct ListNode
{
    int m_value ;
    ListNode* m_pNext;
}

void DeleteNode(ListNode** pListHead ,ListNode* pToBeDeleted);

思路:
在单向链表中删除一个结点,最常用的做法无疑是从链表的头结点开始,顺序遍历查找要删除的结点,并在链表中删除该结点。
我们想删除结点i,可以从链表的头结点a开始顺序遍历,发现结点h的m_pNext指向要删除的结点i,于是我们就可以把结点h的m_pNext指向i的下一个结点即结点j。指针调整之后,我们就可以安全地删除结点i并保证链表没有断开,这种思路的时间复杂度自然是O(n)了。

void DeleteNode(ListNode** pListHead ,ListNode* pToBeDeleted)
{
    if(!pListHead||!pToBeDeleted||!*pListHead)
    return ;
    if(pToBeDeleted== *pListHead)
    {

        *pListHead =  pToBeDeleted->m_pNext;
        delete pToBeDeleted ;
        pToBeDeleted = NULL ; 
    }
    else
    {
        ListNode* pNode = *pListHead ;
        while(pNode->m_pNext!=pToBeDeleted)
        {
            pNode = pNode->m_pNext ;
        }
        pNode->m_pNext = pToBeDeleted->m_pNext ;
        delete pToBeDeleted ; 
        pToBeDeleted = NULL ;
    }
}
a->b->...->h->i->j->....

a->b->...->h->j->....

之所以需要从头开始查找,是因为我们需要得到将被删除的结点的前面一个结点。在单向链表中,结点中没有指向前一个结点的指针,所以只好从链表的头结点开始顺序查找。
那是不是一定需要得到被删除的结点的前一个结点呢?答案是否定的。我们可以很方便地得到要删除的结点的下一结点。如果我们把下一个结点的内容复制到需要删除的结点上覆盖原有的内容,再把下一个结点删除,那是不是相当于把当前需要删除的结点删除了?这里使用一点点小的技巧。
如果要删除的结点位于链表的尾部,那么他就没下一个结点,怎么办?我们仍然从链表的头结点开始,顺序遍历得到该结点的前序结点,并完成删除操作。
最后需要注意的是,如果链表只有一个结点,此时我们在删除结点之后,还需要把链表的头结点设置成NULL。

void DeleteNode(ListNode** pListHead ,ListNode* pToBeDeleted)
{
    if(!pListHead||!pToBeDeleted||!*pListHead)
    return ;
    if(pToBeDeleted->m_pNext!=NULL)
    {
        ListNode* pNext = pToBeDeleted->m_pNext;
        pToBeDeleted->m_value = pNext->m_value;
        pToBeDeleted->m_pNext = pNext->m_pNext;
        delete pNext;
        pNext = NULL;
    }else if(pToBeDeleted==*pListHead)
    {
        *pListHead =NULL ;
        delete pToBeDeleted;
        pToBeDeleted = NULL ;
    }
    else
    {
        ListNode* pNode = *pListHead ;
        while(pNode->m_pNext!=pToBeDeleted)
        {
            pNode = pNode->m_pNext ;
        }
        pNode->m_pNext = NULL;
        delete pToBeDeleted;
        pToBeDeleted = NULL;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值