您的位置:首页 > Web前端

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

2015-11-11 16:55 459 查看
题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:

struct ListNode {

int value;

ListNode *pNext;

};

思路:

一般的删除结点的思路为依次扫描链表,获取被删结点的前向指针,时间复杂度为O(n);

另一种思路是不实际删除本结点,而是大致采用被删结点覆盖别删结点后续结点的方式。

ListNode *t =pToBeDeleted->next;

pToBeDeleted->value = t->value;

pToBeDeleted->next = t->next;

然后删除t结点即可

在这种思路下,被删结点实际上分为三种情况

1、被删结点存在后续结点。时间复杂度为O(1);

2、被删结点不存在后续结点但链表有多个结点,这是仍然需要使用遍历的方式获取被删结点的前向指针,时间复杂度为O(n)。

3、被删链表只存在一个结点,这是需要删除结点并且将头指针赋NULL;

这时的时间复杂度为 O((1*【n-1】+n*【1】)/n),即O(1)。

#include <iostream>
using namespace std;
struct ListNode {
int value;
ListNode *pNext;
};

/**
*判断结点是否属于某链表,属于返回true,不属于返回false
*/
bool isExist(ListNode *pHead,ListNode *p) {
bool exist = false;
if(pHead == NULL || p == NULL) {
exist = false;
}
else {
while(pHead != NULL) {
if(pHead->value == p->value) {
exist = true;
break;
}
pHead = pHead->pNext;
}
}
return exist;
}

/**
*删除链表中的某结点
*/
void DeleteNode(ListNode **pHead, ListNode *pToBeDeleted) {
if(pHead == NULL || pToBeDeleted == NULL) {
return;
}
if(!isExist(*pHead,pToBeDeleted)) {
//所需删除的结点不在链表中
return;
}
//尾结点不为空
if(pToBeDeleted->pNext != NULL) {
ListNode *p = pToBeDeleted->pNext;
pToBeDeleted->value = p->value;
pToBeDeleted->pNext = p->pNext;
delete p;
p = NULL;
}
//链表中只存在一个结点
else if(*pHead == pToBeDeleted) {
delete pToBeDeleted;
*pHead = NULL;
pToBeDeleted = NULL;
}
//链表中只包含多个结点
else {
ListNode *p = *pHead;
while(p->pNext != pToBeDeleted) {
p = p->pNext;
}
p->pNext = NULL;
delete pToBeDeleted;
pToBeDeleted = NULL;
}
}

/**
* 向链表中插入结点
*/
void insertList(ListNode **pHead,ListNode *value) {
ListNode *head = *pHead;
if(head == NULL) {
*pHead = value;
}
else {
while(head->pNext != NULL) {
head = head->pNext;
}
head->pNext = value;
}
}

/**
* 向链表中插入结点
*/
void insertList(ListNode **pHead,int value) {
ListNode *p = new ListNode();
p->value = value;
p->pNext = NULL;
insertList(pHead,p);
}

/**
* 打印链表
*/
void print(ListNode *p) {
while(p) {
cout<<p->value<<" ";
p = p->pNext;
}
cout<<endl;
}

int main() {
//构造链表
ListNode *head = NULL;

ListNode *p1 = new ListNode();
p1->value = 1;
p1->pNext = NULL;
insertList(&head,p1);

ListNode *p2 = new ListNode();
p2->value = 2;
p2->pNext = NULL;
insertList(&head,p2);

ListNode *p3 = new ListNode();
p3->value = 3;
p3->pNext = NULL;
insertList(&head,p3);

ListNode *p4 = new ListNode();
p4->value = 4;
p4->pNext = NULL;

//测试实例
//1,所删结点不在链表中
//2.删除中间普通结点
//3.删除尾结点
//4,删除既是头结点又是尾结点的结点

//1,所删结点不在链表中
DeleteNode(&head,p4);
print(head);
//2.删除中间普通结点
DeleteNode(&head,p2);
print(head);
//3.删除尾结点
//此时最后一个结点已经变成p2,如果参数是p3无效
DeleteNode(&head,p2);
print(head);
//4,删除既是头结点又是尾结点的结点
DeleteNode(&head,p1);
print(head);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  链表 指针