删除链表中的节点,时间复杂度O(1)(剑指offer)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39675633/article/details/78668853

题目: 在O(1)的时间内删除链表的节点

给定当链表的头指针和一个节点的指针,定义一个函数在O(1)的时间复杂度内删除该节点。

#include <cassert>
#include <iostream>
struct ListNode
{
    int mVal;
    ListNode* mpNext;
};
/**
*@pHead 使用指针的指针,使得函数结束后pHead指向的节点有效
*@val 待插入的值
*/
void addNodeToTail(ListNode** pHead, int val)
{
    ListNode* pNewNode = new ListNode;
    pNewNode->mVal = val;
    pNewNode->mpNext = nullptr;
    //如果头节点为空
    if (*pHead == nullptr)
    {
        *pHead = pNewNode;
    }
    else
    {
    ListNode* pNode = *pHead;
    while (pNode->mpNext != nullptr)
        pNode = pNode->mpNext;
        pNode->mpNext = pNewNode;

    }
}

void destroyList(ListNode** pHead)
{
   std::cout << "\nstart free memery..." << std::endl;
    ListNode* pNode = *pHead;
    while (*pHead != nullptr)
    {
            *pHead = (*pHead)->mpNext;
        delete pNode;
        pNode = *pHead;
    }
    std::cout << "free memery complete" << std::endl;
}
//从头到尾打印链表
void printList(ListNode**pHead)
{
    ListNode *pNode =*pHead;
    while (pNode != nullptr)
    {
        std::cout << pNode->mVal << " ";
    pNode = pNode->mpNext;
    }
}
/**
*@pHead 指向链表的头节点
*@val 要查找的元素
*@return 指向查找的元素的位置
*/
ListNode* findVal(ListNode* pHead, int val)
{
    ListNode* toBeFindList = nullptr;
    ListNode* pNode = pHead;
    while (pNode != nullptr && pNode->mVal != val)
    {
        pNode = pNode->mpNext;
    }

    toBeFindList = pNode;
    return toBeFindList;
}

/**
*@pHead 指向链表头节点的指针
*@pToBeDeleted 指向要删除的节点
*/
void deleteNode(ListNode** pHead, ListNode* pToBeDeleted)
{
    //单链表为空, 直接返回
    if (pHead == nullptr || (*pHead) == nullptr)
        return;
    //要删除的节点不是尾节点
    if (pToBeDeleted->mpNext != nullptr)
    {
        ListNode* pNext = pToBeDeleted->mpNext;
    pToBeDeleted->mVal = pNext->mVal;
    pToBeDeleted->mpNext = pNext->mpNext;

    delete pNext;
    pNext = nullptr;
    }
    else if (*pHead == pToBeDeleted)  //链表中只有一个节点,删除该节点(即删除的节点是头节点或者尾节点)
    {
        delete pToBeDeleted;
    pToBeDeleted = nullptr;

    *pHead = nullptr;
    }
    else // 链表中有多个节点且删除的节点是尾节点
    {
     ListNode* pNode = *pHead;
     while (pNode->mpNext != pToBeDeleted)
     {
         pNode =pNode->mpNext;
     }

     pNode->mpNext = nullptr;
     delete pToBeDeleted;
     pToBeDeleted = nullptr;
    }
}
/**
*测试用例
*注意元素0表示输入的结束标志,并不把它存在链表中
*例如输入链表 1 2 3 4 0
*/
int main(int argc, char* argv[])
{
    std::cout << "\n--提示: 输入元素 0 为输入结束的标志" << std::endl;
    ListNode* pHead = nullptr;
    int val;
    //val == 0为结束标志
    while (std::cin >> val && val != 0)
        addNodeToTail(&pHead,  val);
    std::cout << "打印初始化链表:";
    printList(&pHead);
    std::cout << "\n输入要删除的元素 : ";
    int find_val;
    while (std::cin >> find_val && find_val != 0)
    {
        ListNode* toBeFindNode = findVal(pHead, find_val);
        if (toBeFindNode != nullptr)
        {
        std::cout << "找到元素 " << find_val << " 并将它从链表中删除" << std::endl;
        deleteNode(&pHead, toBeFindNode);
            std::cout << std::endl << "链表中剩余的元素有: ";
        printList(&pHead);
    }
    else
    {
       std::cout << "元素 " << find_val << " 不在链表中" << std::endl;
       printList(&pHead);
    }
        std::cout << "\n输入要删除的元素 : ";
    }
   //释放申请的内存空间
    destroyList(&pHead);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39675633/article/details/78668853
今日推荐