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

struct ListNode
{
    int m_nValue;
    ListNode* m_pNext;
};

//方法1:常规法,顺序查找要被删除的节点,时间复杂度为O(n)
void DeleteNode_1(ListNode** pListHead, ListNode* pToBeDeleted)
{
    if (pListHead == nullptr || *pListHead == nullptr)
        return;

    //若被删除的是首元节点,则将头指针指向第二个节点,删除首元节点
    if ((*pListHead)->m_pNext == pToBeDeleted)
    {
        pToBeDeleted = (*pListHead)->m_pNext;
        (*pListHead)->m_pNext = pToBeDeleted->m_pNext;
    }
    //若删除的是中间节点,则遍历链表至被删除节点的前驱
    else
    {
        ListNode* p = *pListHead;
        while (p->m_pNext!=pToBeDeleted&&p->m_pNext!=nullptr)
        {
            p = p->m_pNext;
        }
        pToBeDeleted = p->m_pNext;
        p->m_pNext = pToBeDeleted->m_pNext;
    }

    //判断要删除的节点是否非空,即是否真的存在这个要删除的节点
    if (pToBeDeleted != nullptr)
    {
        delete pToBeDeleted;
        pToBeDeleted = nullptr;
    }
}

/*
方法2:特殊方法,不用顺序查找被删除的节点的前一个节点,而是只利用其后继节点,
用后继节点的值覆盖本该删除的那个节点,然后删除后继节点。时间复杂度为O(1)
*/
void DeleteNode_2(ListNode** pListHead, ListNode* pToBeDeleted)
{
    if (pListHead == nullptr || *pListHead == nullptr)
        return;
    //若该节点不为尾节点,有后继节点
    if (pToBeDeleted->m_pNext != nullptr)
    {
        pToBeDeleted->m_nValue = pToBeDeleted->m_pNext->m_nValue;
        pToBeDeleted = pToBeDeleted->m_pNext;
    }

    //若该节点为尾结点,无后继节点,则需顺序查找尾结点的前驱结点。
    else
    {
        ListNode* p = *pListHead;
        while (p->m_pNext!=pToBeDeleted&& p->m_pNext!=nullptr)
        {
            p = p->m_pNext;
        }
        pToBeDeleted = p->m_pNext;
        p->m_pNext = pToBeDeleted->m_pNext;
    }

    if (pToBeDeleted != nullptr)
    {
        delete pToBeDeleted;
        pToBeDeleted = nullptr;
    }
}