数据结构--单链表的插入&删除

2023-11-18

数据结构–单链表的插入&删除

目标
单链表的插入(位插、前插、后插)
单链表的删除

单链表的插入

按为序插入(带头结点)

ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。

思路:找到第i-1个结点,将新结点插入其后

代码实现

typedef struct LNode
{
    ElemType data;  
    struct LNode *next; 
}LNode, *LinkList;

bool ListInsert(LinkList &L, int i, ElemType e)
{
    if (i < 1)  return false;

    LNode *p = L; //L指向头结点,头结点是第0个结点(不存数据)
    int j = 0; //当前p指向的是第几个结点
    while (p != NULL && j < i - 1) //循环找到第i-1个结点
    {
        p = p->next;
        j++;
    }
    if (p == NULL)  return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    s->next = p->next;
    s->data = e;
    p->next = s;
    return true;
}

时间复杂度

最好时间复杂度 O(1)
最坏时间复杂度 O(1)
平均时间复杂度 O(1)

按位序插入(不带头结点)

思路:找到第i-1个结点,将新结点插入其后

代码实现

typedef struct LNode
{
    ElemType data;  
    struct LNode *next; 
}LNode, *LinkList;


bool ListInsert(LinkList &L, int i, ElemType e)
{
    if (i < 1)  return false;

    if (i == 1) //插入第1个结点的操作与其他结点操作不同
    {
        LNode* s = (LNode*)malloc(sizeof(LNode));
        s->data = e;
        s->next = L;
        L = s;
        return true;
    }

    LNode *p = L; //L指向头结点,头结点是第0个结点(不存数据)
    int j = 0; //当前p指向的是第几个结点
    while (p != NULL && j < i - 1) //循环找到第i-1个结点
    {
        p = p->next;
        j++;
    }
    if (p == NULL)  return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    s->next = p->next;
    s->data = e;
    p->next = s;
    return true;
}

结论:
不带头写代码更不方便,推荐用带头结点
注意:考试中带头、不带头都有可能考察,注意审题

指定结点的后插操作

代码实现
typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode, *LinkList;

bool InsertNextNode(LNode* p, ElemType e)
{
    if (p == NULL)  return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL)  return false; // 内存分配失败
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}

指定结点的前插操作

前插操作:在p结点之前插入元素e
bool InsertPriorNode (LNode *p,ElemType e)

方法一:
bool InsertPriorNode (LinkListL L, Node *p,ElemType e)
传入头指针,循环查找p的前驱,再对q后插
时间复杂度:O(n)

方法二 \color{red}方法二 方法二

方法二实现代码

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode, *LinkList;

bool InsertPriorNode (LNode *p,ElemType e)
{
    if (p == NULL)  return false;

    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL)  return false;
    s->next = p->next;
    p->next = s; //新结点s连到p之后
    s->data = p->data; //将p中元素复制到s中
    p->data = e; //p 中元素覆盖为e
    return true;
}

时间复杂度: O(n)

前插操作:在p结点之前插入结点 s

代码实现
bool InsertPriorNode(LNode* p, LNode* s)
{
    if (p == NULL || s == NULL) return false;

    s->next = p->next;
    p->next = s;
    ElemType tmp = p->data;
    p->data = s->data;
    s->data = tmp;
    return true;
}

单链表的删除

按位序删除(带头结点)

ListDelete(&L,i,&e):删除操作。删除表L中第i个位置的元素,并用e返回删除元素的值。

方法:
找到第i-1个结点,将其指针指向第i+1个结点,并释放第i个结点

代码实现

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode, *LinkList;

bool ListDelete(LinkList &L, int i, ElemType &e)
{
    if (i < 1)  return false;
    LNode *p = L;
    int j = 0;
    while (p != NULL && j < i - 1)
    {
        p = p->next;
        j++;
    }
    if (p == NULL)  return false;
    if (p->next == NULL)    return false; //第i-1个结点之后已无其他结点

    LNode* q = p->next;
    e = q->data; //用e返回元素的值
    p->next = q->next; //将*q结点从链中“断开"
    free(q); //释放结点的存储空间
    return true;
}

时间复杂度:O(n)

删除指定结点p

bool DeleteNode ( LNode *p)

方法1:传入头指针,循环寻找p的前驱结点
时间复杂度O(n)
方法2:偷天换日(类似于结点前插的实现)
时间复杂度O(1)

方法二代码实现
typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode, *LinkList;

bool DeleteNode(LNode* p)
{
    if (p == NULL)  return false;

    LNode* q = p->next; //令q指向*p的后继结点
    p->data = p->next->data; //和后继结点交换数据域
    p->next = q->next; //将*q结点从链中"断开"
    free(q);
    return true;
}

注: \color{red}注: 注:
如果 p 是最后一个结点,只能从表头开始依次寻找 p 的前驱 , 时间复杂度 O ( n ) \color{red} 如果p是最后一个结点,只能从表头开始依次寻找p的前驱,时间复杂度O(n) 如果p是最后一个结点,只能从表头开始依次寻找p的前驱,时间复杂度O(n)

知识点回顾与重要考点

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构--单链表的插入&删除 的相关文章

  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 重载<<的返回值

    include
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new

随机推荐

  • VTK配置步骤(WIN7 64位 + VS2012 + VTK-5.10.1)

    前面的废话可以不看 我很啰嗦 由于项目中需要用到VTK 上周三就开始编译VTK源码 中间出现了一系列问题 首先是下载的高版本代码顺利编译后 自己新建的工程总是提示链接错误 尽管所有的库文件都加入了 还是不正确 之后下载了vtk较低版本5 8
  • 一文带你了解降压型稳压芯片原理

    一文带你了解降压型稳压芯片原理 导读 在电路系统设计中 总是离不开电源芯片的使用 林林总总的电源芯片非常多 比如传统的线性稳压器7805 低压差线性稳压器 LDO 开关型降压稳压器 Buck DCDC 等 那么它们到底有什么区别呢 Exce
  • C# 基本语法

    C 基本语法 C 是一种面向对象的编程语言 在面向对象的程序设计方法中 程序由各种相互交互的对象组成 相同种类的对象通常具有相同的类型 或者说 是在相同的 class 中 例如 以 Rectangle 矩形 对象为例 它具有 length
  • java request获取数组

    获取单一参数 String hostName request getParameter host String url request getParameter url 获取参数数组 String carrier request getPa
  • Ubuntu 16.04 搭建Hadoop环境(to be continued)

    reference 1 Ubuntu上搭建Hadoop环境 单机模式 伪分布模式 by yinlung 2 Ubuntu11 10下安装Hadoop1 0 0 单机伪分布式 3 Ubuntu上搭建Hadoop环境 单机模式 伪分布模式 by
  • 2023养老服务人才状况调查报告

    导读 本次调查内容涉及养老服务人才的基本特征 待遇和保障状况 培训状况 职业发展状况等 调查显示 养老服务人才以女性为主 各类受访者中女性占比约82 3 养老服务人才队伍年龄结构偏大 41 55岁年龄段的受访者占比56 0 56岁及以上占比
  • 安装Java (JDK16)

    本文将在win10的环境下安装jdk16 配置环境变量 1 下载JDK 1 打开官网下载最新的JDK Java SE Development Kit JDK 2 选择对应的版本 3 双击下载的exe进行安装 在安装过程中可以改变安装位置也可
  • MyBatis-Generator插入删除数据返回-2147482646

    在使用MyBatis Generator自动生成的代码进行删除数据时 deleteByPrimaryKey 方法 返回的int 值为 2147482646 正常的逻辑是成功删除返回 1 失败返回 0 未删除数据 特意去官网看了这个方法的说明
  • JAVA 数组(一维数组)

    Java 语言中提供的数组是用来存储固定大小的同类型元素 即存储同种数据类型的多个值 1 声明数组变量和数组初始化 首先必须声明数组变量 才能在程序中使用数组 语法 dataType arrayRefVar 或 dataType array
  • King's Quest【POJ 1904】【Tarjan强连通分量】

    Once upon a time there lived a king and he had N sons And there were N beautiful girls in the kingdom and the king knew
  • CNN,RNN,LSTM区别

    一 CNN 卷积神经网络 在机器学习中 卷积神经网络是一种深度前馈人工神经网络 已成功地应用于图像识别 1 卷积神经网络 是一种前馈神经网络 人工神经元可以响应周围单元 可以进行大型图像处理 卷积神经网络包括卷积层和池化层 卷积神经网络包括
  • 盒子模型大详解

    文档流 网页是一个多层结构 设置样式也是一层一层设置的 最终我们看到的是最上面的那一层 文档流就是网页最底部 我们创建的元素默认都是在文档流中创建的 元素分为两种状态 在文档流 脱离文档流 元素在文档流的特点 块元素 1 独占一行 2 宽是
  • 手机iCloud储存空间已满,怎么解决?

    最近手机总是弹出iCloud储存空间已满 升级的话得花钱 以后再说的话 总感觉有点 不安 担心自己的照片啥的会存不了 所以特意查找了这种方法 如果有出现这种情况的朋友 可以试试 1 找出iCloud空间被哪些档案塞满 iiPhone或iPa
  • Linux之mmv命令批量替换文件名(超详细-python结合mmv)

    文章目录 一 前言 二 各系统安装mmv方法 2 1 CentOS 2 2 Ubuntu And Debain 2 3 MacOS 三 使用方法 3 1 常规使用 3 1 1 常规使用示例 3 2 携带参数使用 3 2 1 携带参数使用示例
  • vue3.x之isRef toRefs isRef readonly 公共数据配置 axios配置 路由配置

    isRef toRefs toRef 参数 源对象 源对象属性 可以用来为源响应式对象上的某个 property 新创建一个 ref 然后 ref 可以被传递 它会保持对其源 property 的响应式连接 也就是说源响应式对象 toRef
  • 3427: Dark roads

    http cs scu edu cn soj problem action id 3427 Description Economic times these days are tough even in Byteland To reduce
  • 向量二范数的求导问题

    现有目标函数 f x 1 2
  • ant design pro 可编辑表格

    import React useRef from react import PageHeaderWrapper from ant design pro layout import ProColumns ActionType TableDro
  • python elif 用法,在Python列表推导中对if / elif语句使用'for'循环

    I am trying to translate this for loop into a list comprehension a 1 2 3 4 5 6 7 8 9 result for i in a if i lt 3 result
  • 数据结构--单链表的插入&删除

    数据结构 单链表的插入 删除 目标 单链表的插入 位插 前插 后插 单链表的删除 单链表的插入 按为序插入 带头结点 ListInsert L i e 插入操作 在表L中的第i个位置上插入指定元素e 思路 找到第i 1个结点 将新结点插入其