您的位置:首页 > Web前端

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

2017-10-13 15:36 471 查看
面试题13:给定单项链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。

//不带头结点的单链表
struct ListNode
{
int m_nKey;
ListNode *m_pNext;
};

//尾插
void InsertTail(ListNode **head,int key)
{
ListNode *newnode = new ListNode();
newnode->m_nKey = key;
newnode->m_pNext = NULL;

if(*head == NULL)
{
*head = newnode;
}
else
{
ListNode *p = *head;
while(p->m_pNext != NULL)
p = p->m_pNext;

p->m_pNext = newnode;
}
}

/*假设该结点在链表中。
如果不假设,我们需要O(n)的时间才能判断链表中是否包含该结点。基于O(1)的限制,只能把确保结点在链表中的要求推给函数调用者*/
void DeleteNode(ListNode **head,ListNode *deletenode)
{
if(head==NULL || deletenode==NULL)
return;
//删除的节点不是尾节点
if(deletenode->m_pNext != NULL)
{
ListNode *p = deletenode->m_pNext;
deletenode->m_nKey = p->m_nKey;
deletenode->m_pNext = p->m_pNext;
delete(p);
p = NULL;
}
//链表只有一个节点,删除的是尾节点
else if(*head == deletenode)
{
delete deletenode;
deletenode = NULL;
*head = NULL;
}
//链表有多个节点,删除的是尾节点
else
{
ListNode *p = *head;
while(p->m_pNext != deletenode)
{
p = p->m_pNext;
}
p->m_pNext = NULL;

delete deletenode;
deletenode = NULL;
}
}

void Show(ListNode *head)
{
for(ListNode *p=head;p!=NULL;p=p->m_pNext)
{
cout<<p->m_nKey<<ends;
}
cout<<endl;
}

int main()
{
ListNode *head = NULL;
for(int i=0;i<10;i++)
{
InsertTail(&head,i);
}
cout<<"删除前:";
Show(head);

cout<<"删除第三个元素:";
DeleteNode(&head,head->m_pNext->m_pNext);
Show(head);

cout<<"删除首元素:";
DeleteNode(&head,head);
Show(head);

ListNode *p = head;
while(p->m_pNext != NULL) p = p->m_pNext;
cout<<"删除尾元素:";
DeleteNode(&head,p);
Show(head);
}




对于一个n-1非尾结点而言,可以在O(1)时把下一个结点的内存复制覆盖要删除的结点,并删除下一个结点;对于尾结点来说,由于仍需要顺序查找,时间复杂度为O(n)。总的时间复杂度是[(n-1)*O(1)+O(n)]/n,结果是O(1)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  链表 删除结点