题目: 在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;
}