题目:
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};
void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted);
在单向链表中删除一个结点,最常规的做法就是从链表的头结点开始,顺序遍历查找要删除的结点并通过调整指针来删除结点。这种方法时间复杂度为O(n)。
需要从头遍历是为了得到被删除结点的前一个结点p,然后通过p->next=p->next->next实现删除p->next;
换个思路,是否可以不得到前一个结点也能实现删除呢?
借助要删除结点i的下一个节点j!显然这个很容易得到。
删除结点i,可以先将j的内容复制给i,然后把i的指针指向j的下一个结点,此时删除结点j,等效于删除i。
但是如果要删除的结点位于链表尾部,那么就不存在下一个结点。此时仍然从链表头结点开始顺序遍历到该待删结点的前序结点。
如果链表中只有一个结点,而我们又要删除链表的头结点,此时删完之后,需要把链表头结点设置为NULL。
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;
delete pNext;
pNext=NULL;
}
//链表只有一个结点,删除头结点
else if(*pListHead==pToBeDeleted)
{
delete pToBeDeleted;
pToBeDeleted=NULL;
*pListHead==NULL;
}
//链表中有多个结点,删除尾节点
else
{
ListNode* pNode;
while(pNode->m_pNext!=pToBeDeleted)
{
pNode=pNode->m_pNext;
}
pNode->m_pNext=NULL;
delete pToBeDeleted;
pToBeDeleted=NULL;
}
}