说删链表节点,第一时间想到就是遍历整个链表,找到删除节点的前驱,改变节点指向,删除节点,但是,这样删除单链表的某一节点,时间复杂度就是O(n),不符合要求;

时间复杂度是O(n)的做法就不说了,看看O(1)的写法,看图:

删除节点,需要找到被删节点的前驱,上面的说明,交换数据后,要删的节点转换为被删节点的后一个节点,此时被删节点前驱可以知道,删除就很简单了

给出被删节点指针,O(1)时间内就可以有此方法删除节点,但是,如果,被删节点是链表最后一个节点,以上方法明显不在适用,不得不从头遍历:

这时就得从头遍历,只为找最后一个节点的前驱,就这唯一一个节点,找它的时间复杂度就是O(n),但平均时间复杂度为:

((n-1)*O(1)+O(n))/n

结果还是O(1),复合要求的,又但是,这里没有考虑要删除的节点是否在链表中,如果要判断有没有在链表中,又得遍历,结果时间复杂度有不在是O(1),

为了保证时间,被删的节点有没有在链表中,只能由人为的去控制;以下是代码段:

	//在O(1)时间内,删除一个节点,函数如下
void DeleteNodeNumone(ListNode** phead,ListNode* pToBeDelete)
{
if (*phead == nullptr || pToBeDelete == nullptr)
return; //删除非尾节点
if (pToBeDelete->_next != nullptr)
{
ListNode* temp = pToBeDelete->_next;
pToBeDelete->_data = temp->_data;
pToBeDelete->_next = temp->_next; delete temp;
temp = nullptr;
} //只有一个节点
else if (*phead == pToBeDelete)
{
delete pToBeDelete;
pToBeDelete = nullptr;
*phead = nullptr;
} //最后一种,删除节点是尾节点
else
{
ListNode* cur = *phead;
while (cur->_next != pToBeDelete)
{
cur = cur->_next;
}
delete pToBeDelete;
pToBeDelete = nullptr;
cur->_next = nullptr;
}
}

完整测试代码:

#pragma once
typedef int DataType; class ListNode
{
public:
ListNode(const DataType& x)
:_data(x)
, _next(NULL)
{} public:
DataType _data;
ListNode* _next;
}; class Slist
{
public:
Slist()
:_head(NULL)
, _tail(NULL)
{}
~Slist()
{
//析构函数,删除节点,删除全部
Destory();
} void Destory()
{
ListNode* begin = _head;
while (begin)
{
ListNode* del = begin;
begin = begin->_next;
delete del;
}
} public:
//尾插
void PushBack(const DataType& x)
{
if (_head == NULL)
{
_head = new ListNode(x); _tail = _head;
}
else
{
_tail->_next = new ListNode(x);
_tail = _tail->_next;
}
} //查找
ListNode* Find(const DataType& x)
{
ListNode* tmp = _head;
while (tmp)
{
if (tmp->_data == x)
return tmp;
else
{
tmp = tmp->_next;
}
}
return NULL;
} // //在O(1)时间内,删除一个节点,函数如下
void DeleteNodeNumone(ListNode** phead,ListNode* pToBeDelete)
{
if (*phead == nullptr || pToBeDelete == nullptr)
return; //删除非尾节点
if (pToBeDelete->_next != nullptr)
{
ListNode* temp = pToBeDelete->_next;
pToBeDelete->_data = temp->_data;
pToBeDelete->_next = temp->_next; delete temp;
temp = nullptr;
} //只有一个节点
else if (*phead == pToBeDelete)
{
delete pToBeDelete;
pToBeDelete = nullptr;
*phead = nullptr;
} //最后一种,删除节点是尾节点
else
{
ListNode* cur = *phead;
while (cur->_next != pToBeDelete)
{
cur = cur->_next;
}
delete pToBeDelete;
pToBeDelete = nullptr;
cur->_next = nullptr;
}
} void print()
{
ListNode* begin = _head;
while (begin)
{
cout << begin->_data << "->";
begin = begin->_next;
}
cout << "NULL" << endl;
} public:
ListNode* _head;
ListNode* _tail;
};
void Test()
{
Slist s1;
s1.PushBack(5);
s1.PushBack(2);
s1.PushBack(3);
s1.PushBack(2);
s1.PushBack(1);
s1.PushBack(6);
s1.PushBack(7);
s1.PushBack(9);
s1.print(); ListNode* num =s1.Find(9); s1.DeleteNodeNumone(&s1._head, num); s1.print();
}

测试结果:

赐教!

单向链表在O(1)时间内删除一个节点的更多相关文章

  1. LeetCode-450 二叉搜索树删除一个节点

    二叉搜索树 建树 删除节点,三种情况,递归处理.左右子树都存在,两种方法,一种找到左子树最大节点,赋值后递归删除.找右子树最小同理 class Solution { public: TreeNode* ...

  2. Linus:利用二级指针删除单向链表

    Linus大神在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是他所喜好的,大婶表述了自己一些观点之后,举了一个指针的例子,解释了什么才是core low-level codi ...

  3. 【转】Linus:利用二级指针删除单向链表

    原文作者:陈皓 原文链接:http://coolshell.cn/articles/8990.html 感谢网友full_of_bull投递此文(注:此文最初发表在这个这里,我对原文后半段修改了许多, ...

  4. 转:Linus:利用二级指针删除单向链表

    感谢网友full_of_bull投递此文(注:此文最初发表在这个这里,我对原文后半段修改了许多,并加入了插图) Linus大婶在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是 ...

  5. 在O(1)的时间内删除链表节点

    题目: 在O(1)的时间内删除链表节点.给定链表的头指针和待删除的节点指针,定义一个函数在O(1)的时间内删除该节点. 剑指offer的思路,顿时觉得极妙.删除节点node1,先把其下一个节点node ...

  6. 用Python写单向链表和双向链表

    链表是一种数据结构,链表在循环遍历的时候效率不高,但是在插入和删除时优势比较大. 链表由一个个节点组成. 单向链表的节点分为两个部分:存储的对象和对下一个节点的引用.注意是指向下一个节点. 而双向链表 ...

  7. Reverse Linked List II 单向链表逆序(部分逆序)

    0 问题描述 原题点击这里. 将单向链表第m个位置到第n个位置倒序连接.例如, 原链表:1->2->3->4->5, m=2, n =4 新链表:1->4->3-& ...

  8. 数据结构——求单向链表的倒数第K个节点

    首先,对于链表来说,我们不能像数组一样直接访问,所以我们想到要求倒数第K个节点首先要知道最后一个节点. 然后从最后一个节点往前数K个. 最后得到想要的值. 但是这是不对的,为什么呢?因为题目给出的是单 ...

  9. 剑指offer25:复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),结果返回复制后复杂链表的head。

    1 题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用 ...

随机推荐

  1. RobotFramework自动化测试框架-移动手机自动化测试Open Application关键字的使用

    在AppiumLibrary库中,Open Application关键字用来打开一个待测试移动APP. 示例1:连接本机已经打开的appium服务端,打开一个待测试的安卓APP,指定测试平台为Andr ...

  2. RLS自适应滤波器中用矩阵求逆引理来避免求逆运算

    在RLS自适应滤波器的实现过程中,难免不涉及矩阵的求逆运算.而求逆操作双是非常耗时的,一个很自然的想法就是尽可能的避免直接对矩阵进行求逆运算.那么,在RLS自适应滤波器的实现中,有没有一种方法能避免直 ...

  3. 【BZOJ2527】MET-Meteors(整体二分)

    [BZOJ2527]MET-Meteors(整体二分) 题面 BZOJ权限题,良心洛谷链接 题解 其实我也不会做 看了zsy博客才会做... 这题如果直接爆算做显然行不通 如果只有单次询问,我们就可以 ...

  4. [BZOJ3668] [Noi2014] 起床困难综合症 (贪心)

    Description 21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争.通过研究相关文献,他找 ...

  5. 分布式架构设计(一) --- 面向服务的体系架构 SOA

    1.1 基于TCP协议的RPC 1.1.1 RPC名词解释 RPC的全称是Remote Process Call,即远程过程调用,RPC的实现包括客户端和服务端,即服务调用方和服务提供方.服务调用方发 ...

  6. MMORPG中的相机跟随算法

    先上代码 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Cam ...

  7. cesium Animation显示系统时间

    var d = new Date(); var hour = 0 - d.getTimezoneOffset(); viewer.animation.viewModel.timeFormatter = ...

  8. overflow-x后覆盖滚动条

    可以看到,上面的导航是fixed定位,微信下载,这 部分也是fixed定位, 出现的原因初步判定是:给html与body加overflow-x:hidden:导致, 解决办法是,去掉html的over ...

  9. Hibernate 一对一关联映射,mappedBy参数解析

    在最近java,SSH框架的学习中遇到了这样的一个问题,在Hibernate的开发中一对一关联映射的单向关联,主表会在次表新增一列次表的主键如下图,但是在双向关联中次表不会在表中创建主表的主键一列,这 ...

  10. 请详细描述(以硬盘启动)Linux系统从打开主机电源到进入登录界面整个过程的流程。

    1. 开机进行BIOS(BIOS(Basic Input / Output System)自检测系统外围硬件设备如CPU.内存.IO.显卡.鼠标键盘等.根据BIOS中设置的系统启动顺序搜索用于启动系统 ...