您的位置:首页 > 职场人生

剑指Offer----面试题13:在O(1)时间删除链表结点

2016-06-03 18:32 861 查看

题目:

给定单向链表的头结点和一个指针结点,定义一个函数在O(1)时间删除该结点。

方法一:

在以往的算法中,我们往往都是从链表的头结点开始循环遍历找到该结点的前一个结点a,通过调整该结点a的指针来删除结点,然而这种算法的时间复杂度为O(n),如下如所示:





我们也可以找到该结点i的下一个结点j,将j的内容复制到需要删除的结点i上来覆盖掉其原有的内容,然后再把下一个结点j删掉就可以了!如下图所示:



源代码:

List.h

#ifndef LIST_NODE_H
#define LIST_NODE_H

namespace ListSpace2
{

struct ListNode
{
int element;
ListNode *next;
};

ListNode * CreateListNode(int valude);
void ConnectListNodes(ListNode *pCurrent, ListNode *pNext);
void printListNode(ListNode *pHead);
void printList(ListNode *pHead);
void printReversingly_Iteratively(ListNode *pHead);
void printReversingly_Recursively(ListNode *pHead);
void DestoryList(ListNode **pHead);
void AddToTail(ListNode ** pHead, int value);
void RemoveNode(ListNode ** pHead, int value);

}

#endif


List.cpp
#include"List.h"
#include<iostream>
#include<stack>

namespace ListSpace2
{
ListNode * CreateListNode(int value)
{
ListNode *pNew = new ListNode();
pNew->element = value;
pNew->next = NULL;

return pNew;
}

void ConnectListNodes(ListNode *pCurrent, ListNode *pNext)
{
if (pCurrent == NULL)
std::cout << "Linking Error..." << std::endl;
else
{
pCurrent->next = pNext;
}
}

void printListNode(ListNode *pHead)
{
if (pHead == NULL)
std::cout << "The value of this node is empty" << std::endl;
else
std::cout << "The value of this node is " << pHead->element << std::endl;
}

void printList(ListNode *pHead)
{
if (pHead == NULL)
std::cout << "The list is empty" << std::endl;
else
{
ListNode *pNew = pHead;
while (pNew != NULL)
{
std::cout << pNew->element << "  ";
pNew = pNew->next;
}
}
}

void printReversingly_Iteratively(ListNode *pHead)
{

if (pHead == NULL)
{
std::cout << "The list is empty" << std::endl;
return;
}
else
{
std::stack<ListNode *> st;
ListNode * pNew = pHead;
while (pNew != NULL)
{
st.push(pNew);
pNew = pNew->next;
}

while (!st.empty())
{
std::cout << st.top()->element << "  ";
st.pop();
}
}
}

void printReversingly_Recursively(ListNode *pHead)
{
if (pHead != NULL)
{
if (pHead->next != NULL)
printReversingly_Recursively(pHead->next);
std::cout << pHead->element << "  ";
}
}

void DestoryList(ListNode **pHead)
{
ListNode *pNew = *pHead;
while (pNew != NULL)
{
*pHead = (*pHead)->next;
delete pNew;
pNew = *pHead;
}
}

void AddToTail(ListNode ** pHead, int value)
{
ListNode *pNew = new ListNode();
pNew->element = value;
pNew->next = NULL;

if (*pHead == NULL)
*pHead = pNew;
else
{
//找到最后一个结点
ListNode *node = *pHead;
while (node->next != NULL)
node = node->next;

node->next = pNew;
}
}

void RemoveNode(ListNode ** pHead, int value)
{
if (pHead == NULL || *pHead == NULL)
return;

ListNode *pToBeDeleted = NULL;
if ((*pHead)->element == value)
{
pToBeDeleted = *pHead;
*pHead = (*pHead)->next;
}
else
{
ListNode *node = *pHead;
while (node->next != NULL && node->next->element != value)
node = node->next;
if (node->next != NULL && node->next->element == value)
{
pToBeDeleted = node->next;
node->next = node->next->next;
}
}

if (pToBeDeleted != NULL)
{
delete pToBeDeleted;
pToBeDeleted = NULL;
}
}
}


主函数

#include"List.h"
#include<iostream>

using std::cout;
using std::endl;

using namespace ListSpace2;

void DeleteNode(ListNode **pHead, ListNode *pToBeDeleted)
{
if (pHead == NULL || pToBeDeleted == NULL)
{//结点为空,删除失败!
cout << "删除结点失败!" << endl;
return;
}

//怎么判断被删除的结点是否为单向链表的结点呢?
//因为如果该结点不是链表中的结点,那么删除该结点是没有意义的!

//链表中有多个结点,且被删除的结点不是尾结点
if (pToBeDeleted->next != NULL)
{
ListNode *temp = pToBeDeleted->next;
pToBeDeleted->element = pToBeDeleted->next->element;
pToBeDeleted->next = pToBeDeleted->next->next;

delete temp;
temp = NULL;
}
//链表中只有一个结点,删除头结点
else if (*pHead == pToBeDeleted)
{
delete *pHead;
*pHead = NULL;
pToBeDeleted = NULL;
}
//链表中有多个结点,删除最后一个结点
else
{
ListNode *temp = *pHead;

while (temp->next != pToBeDeleted)
temp = temp->next;

temp->next = NULL;
delete pToBeDeleted;
pToBeDeleted = NULL;
}
}

//删除多结点链表中非尾结点的链表
void test1()
{
cout << "===========删除多结点链表中非尾结点的链表=============" << endl;
ListNode *list1 = CreateListNode(1);
ListNode *list2 = CreateListNode(2);
ListNode *list3 = CreateListNode(3);
ListNode *list4 = CreateListNode(4);
ListNode *list5 = CreateListNode(5);
ListNode *list6 = CreateListNode(6);

ConnectListNodes(list1, list2);
ConnectListNodes(list2, list3);
ConnectListNodes(list3, list4);
ConnectListNodes(list4, list5);
ConnectListNodes(list5, list6);

printList(list1);
cout << endl;
DeleteNode(&list1, list3);
printList(list1);
cout << endl;
}

//删除多结点链表中尾结点的链表
void test2()
{
cout << "===========删除多结点链表中尾结点的链表=============" << endl;
ListNode *list1 = CreateListNode(1);
ListNode *list2 = CreateListNode(2);
ListNode *list3 = CreateListNode(3);
ListNode *list4 = CreateListNode(4);
ListNode *list5 = CreateListNode(5);
ListNode *list6 = CreateListNode(6);

ConnectListNodes(list1, list2);
ConnectListNodes(list2, list3);
ConnectListNodes(list3, list4);
ConnectListNodes(list4, list5);
ConnectListNodes(list5, list6);

printList(list1);
cout << endl;
DeleteNode(&list1, list6);
printList(list1);
cout << endl;
}

void test3()
{
cout << "===========删除单结点链表中头结点的链表=============" << endl;
ListNode *list1 = CreateListNode(1);
printList(list1);
cout << endl;
DeleteNode(&list1, list1);
printList(list1);
cout << endl;
}

void test4()
{
cout << "===========删除空链表中空结点的链表=============" << endl;
DeleteNode(NULL, NULL);
}

int main()
{
test1();
test2();
test3();
test4();

system("pause");
return 0;
}


运行结果:
===========删除多结点链表中非尾结点的链表=============
1  2  3  4  5  6
1  2  4  5  6
===========删除多结点链表中尾结点的链表=============
1  2  3  4  5  6
1  2  3  4  5
===========删除单结点链表中头结点的链表=============
1
The list is empty

===========删除空链表中空结点的链表=============
删除结点失败!
请按任意键继续. . .


分析:对于n-1个非尾结点而言,时间复杂度为O(1),对于尾结点而言,时间复杂度为O(n),总的时间复杂度为((n-1)*O(1) + O(n))/n,其结果还是O(1)。

注意:题目中没有判断被删除的结点是否为链表中的结点!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 剑指offer 面试题