面试题13:在O(1)时间删除链表结点
一.题目描述
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};
void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted);
二.分析问题
1.解题思路
我们要删除结点i,先把i的下一个结点j的内容复制到i,然后把i的指针指向结点j的下一个结点。此时再删除结点j,其效果刚好是把结点i给删除了
三.代码
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
if (!pListHead || !pToBeDeleted)
{
return;
}
/*要删除的不是尾节点*/
if (PToBeDeleted->m_pNext != NULL)
{
ListNode* pNext = PToBeDeleted->m_pNext;
PToBeDeleted->m_nValue = pNext->m_nValue;
PToBeDeleted->m_pNext = pNext->m_pNext;
free(pNext);
pNext = NULL;
}
/*链表只有一个结点,删除头结点*/
else if (*pListHead == pToBeDeleted)
{
free(pToBeDeleted);
pToBeDeleted = NULL;
*pListHead = NULL;
}
/*要删除的结点是尾结点*/
else
{
ListNode* pNode = *pListHead;
while (pNode->m_pNext != pToBeDeleted)
{
pNode = pNode->m_pNext;
}
pNode->m_pNext = NULL;
free(pToBeDeleted);
pToBeDeleted = NULL;
}
}
注意:
值得注意的是,上述代码仍然不是完美的代码,因为它基于一个假设:要删除的结点的确在链表中。我们需要O(n)的时间才能判断链表中是否包含某一结点。受到O(1)时间的限制,我们不得不把确保结点在链表中的责任推给了函数DeleteNode的调用者。