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

news2024/11/13 15:16:31

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

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

单链表的插入

按为序插入(带头结点)

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)

知识点回顾与重要考点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/690793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件工程期末报告(登录注册部分)

云小智微校园工具系统的设计与实现成员1注册模块 第一章 绪论 系统的背景描述和概述&#xff1a;可以描述系统服务的对象是学生,满足他们查询课程安排和上课时间的需求。目前市场上确实存在这方面的需求,这款app可以方便学生管理课程。系统采用客户端-服务器架构,运行在安卓平…

自学黑客(网络安全),一般人我劝你还是算了吧(自学网络安全学习路线--第十章 公钥基础设施-PKI)【建议收藏】

文章目录 一、自学网络安全学习的误区和陷阱二、学习网络安全的一些前期准备三、自学网络安全学习路线一、PKI概述1、理论基础2、PKI提供的安全服务 二、数字证书1、数字证书的格式2、数字证书的生命周期3、用JAVA工具生成数字证书 三、PKI组成四、PKI功能五、信任模型六、相关…

基于 Redis 手写一个“秒杀”

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

Git分布式版本控制工具 —— 详细笔记

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

现代操作系统(中)

第三章 内存管理 概述 内存&#xff08;RAM&#xff09;是计算机中一种需要认真管理的重要资源。 经过多年探索&#xff0c;人们提出了分层存储器体系&#xff08;memory hierarchy&#xff09;的概念&#xff0c;即在这个体系中&#xff0c;计算机有若干兆&#xff08;MB&a…

统信UOS系统开发笔记(七):在统信UOS系统上使用linuxdeployqt发布qt程序

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/131411975 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

qt QSqlRelationalTableModel 详解

背景知识&#xff1a; Qt SQL的API分为不同层&#xff1a; 驱动层 驱动层 对于QT是基于C来实现的框架&#xff0c;该层主要包括QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorbase、QSqlDriverPlugin and QSqlResult。这一层提供了特定数据库和SQL API层之间的底层桥梁…

Problem I Rank LED题解 - 2018年第一届GXCPC广西大学生程序设计大赛 正式赛

Problem I Rank LED题解 题目大意 ‘0’到‘9’的数字亮线依次为{6、2、5、5、4、5、6、3、7、6}。 Luras想修改每条光线的位置&#xff0c;使她的新等级尽可能小&#xff0c;同时新等级也是一个不带任何前导零的正整数。 另外&#xff0c;光线总数应与开始时相同。 官方题…

【AIGC】1、爆火的 AIGC 到底是什么 | 全面介绍

文章目录 一、AIGC 的简要介绍二、AIGC 的发展历程三、AIGC 的基石3.1 基本模型3.2 基于人类反馈的强化学习3.3 算力支持 四、生成式 AI&#xff08;Generative AI&#xff09;4.1 单模态4.1.1 生成式语言模型&#xff08;Generative Language Models&#xff0c;GLM&#xff0…

消息处理机制(AOSP4.4.2)

消息处理机制&#xff08;AOSP4.4.2&#xff09; Android 应用程序是通过消息来驱动的&#xff0c;系统为每一个应用程序维护一个消息队列&#xff0c;应用程序的主线程&#xff0c;不断地从这个消息队列中获取消息&#xff08;Looper&#xff09;&#xff0c;然后对消息进行处…

STM32单片机(三)第二节:GPIO输出练习2(LED流水灯)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

3 分钟为英语学习神器 Anki 部署一个专属同步服务器

原文链接&#xff1a;https://icloudnative.io/posts/anki-sync-server/ Anki 介绍 Anki 是一个辅助记忆软件&#xff0c;其本质是一个卡片排序工具--即依据使用者对卡片上的自定义内容进行主动测试、自我评判后&#xff0c;其内部算法根据评判结果更改每张卡片下次测试时间的…

将win上的文件传输到Ubuntu虚拟机

首先获取Ubuntu系统的ip地址&#xff0c;在Ubuntu的Terminal中输入ifconfig&#xff0c;可以看到Ubuntu的ip地址 可以看到我电脑的ip地址是10.0.2.15。更改虚拟机的网络连接 这里以VirtualBox为例&#xff0c;打开VirtualBox设置&#xff0c;选择网络&#xff0c;将连接方式改…

React.JS实战项目(三):图书购物网站

React.JS实战项目(三):图书购物网站 1、菜单 首页图书新书购物车2、首页 首页视频预览 首页预览 首页主要展示了友情链接、图书分类、好书推荐、新书广场等等信息。 首页部分代码展示 <Row><Col

SpringSecurity整合ssm

SpringSecurity 1. SpringSecurity 框架简介 Spring 是非常流行和成功的 Java 应用开发框架&#xff0c;Spring Security 正是 Spring 家族中的成员。Spring Security 基于 Spring 框架&#xff0c;提供了一套 Web 应用安全性的完整解决方 案。 正如你可能知道的关于安全方面…

nexus 配置pypi代理

在研发环境中由于网络限制&#xff0c;无法访问外网&#xff0c;但经常使用npm、maven、pip等工具&#xff0c;这种场景中使用nexus 做代理是一个比较好的解决办法。 在配置pypi代理时&#xff0c;和配置npm、maven代理有所不同&#xff0c;在配置远程地址时&#xff0c;需要将…

我的IDEA插件

文章目录 前言一、.ignore二、Adapter for Eclipse Code Formatter三、Convert YAML and Properties File四、EasyCode五、Free MyBatis Tool六、Maven Helper七、Rainbow Brackets 前言 目前使用比较顺手的插件&#xff0c;具体使用方法自行查阅 一、.ignore git 忽略文件&…

【算法与数据结构】344、LeetCode反转字符串

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;关于变量交换有两种办法&#xff0c;一种是最常见的引入一个临时变量方法&#xff0c;另一种是使用位运…

【Java面试题】Java基础——集合

文章目录 集合的形式List和Set的区别ArrayList和LinkedList的区别ArrayList和数组的区别ArrayList的扩容机制是什么&#xff1f;ArrayList有哪些特点List和Map的区别如何让map存储有序数据如何创建Map?常用的Map有哪些?如何在HashMap中插入一个数据遍历一个 List 有哪些不同的…

高清音频文件如何压缩?分享轻松压缩音频文件的方法!

如何进行音频压缩&#xff1f;在我们日常生活中&#xff0c;音频文件扮演着重要的角色&#xff0c;我们可以通过它们享受音乐、收听播客或处理语音录音等。然而&#xff0c;有时候这些音频文件的大小可能会成为问题&#xff0c;特别是当我们需要在有限的存储空间中存储更多的文…