单链表的定义,插入与删除,查找,建立。

2023-11-01

链表分为:单链表,双链表,循环链表,静态链表

一,单链表的定义

在内存空间中,各个节点在逻辑上相邻,但在物理上不相邻。

在单个的结点内部需要存放 数据域 和 指针域(存放指向下一个结点的指针)

优点:不要求一大片连续空间,改变容量方便

缺点:不可随机存取,要耗费一定的空间存放指针。

定义

typedef struct LNode{         //定义单链表结点类型
    int data;                 //每个节点存放一个数据元素
    struct LNode * next;       //指针指向下一个节点
}LNode,* LinkList;

定义一个结构体类型,内部分别存放 元素 和 指向下一个节点的指针。

并且为了后续方便,在此使用typedef函数,将 struct LNode 简称为LNode.

初始化单链表

//初始化单链表
bool InitList(LinkList &L) {
    /*无头结点
    L = NULL;           //空表,暂未节点
    return true;
    */
    //带头结点
    
    
    L = (LNode*)malloc(sizeof(LNode));
    if (L == NULL) {
        return false;
    }
    L->next = NULL;
    return true;
}
void test() {
    LinkList L;       //声明一个指向单链表的指针
    //初始化一个空表
    InitList(L);
}
//判断单链表是否为空
bool Empty(LinkList L) {
    return (L == NULL);
}

 假设我们以及建立了这样一个单链表

二,单链表插入和删除

插入

1)按位序插入

假设我们将在2,3结点中插入一个新结点

只需要将2结点中的next指针指向新结点,将原指针赋值给新结点的next

//按位插入(带头结点)

 //在单链表L中,第i个结点上插入数据域是e的新结点。
bool ListInsert(LinkList &L ,int i,int  e) {  //在单链表L中,第i个结点上插入数据域是e的新结点。
    if (i < 1) {      
        return false;
    }
    LNode * p;  //指针P指向当前扫描到的结点
    int j = 0;
    p = L; //p指向头结点(无数据)
    while (p != NULL && j<i-1){//循环找到第i-1个结点
        p = p->next;
        j++;
    } 
    if (p == NULL) { //i值不合法
        return false;
    }
    LNode* s = (LNode*)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}

归纳:从头结点开始循环,找到第i-1位的结点。将s(新结点)的地址赋值给i-1位的结点的next,将原来的第i位结点的地址赋值给s的next即可。

*注意i的合法性。

平均时间复杂度o (n);

*如果不带头结点:(需要特殊处理i =1的情况 )

/*  不带头结点
        if (i == 1) {
        LNode* s = (LNode*)malloc(sizeof(LNode));
        s->next = L;
        s->data = e;
        L = s;
        return true;
    }
    */

后插操作

只需将结点1的指针指向新结点,将原指针赋值给新结点的next

 (在结点p后面插入一个元素e)

//按位插入(后插)
bool InsertNextNode(LNode* p, int e) {   //在结点p后面插入一个元素e

    //判断结点p是否存在
    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;
    
}

前插操作

//指定结点的前插
bool InsertPriorNode(LNode* p, int e) {  //在结点P前插入一个新元素e
    //数据跑路型(无需寻找p结点的前驱结点)
    LNode* s = (LNode*)malloc(sizeof(LNode));
    s->data = p->data;
    p->data = e;
    s->next = p->next;
    p->next = s;
}
bool InsertPriorNode2(LNode* t, LNode* s) { //在结点P前插入一个新结点S
    if (t = NULL) {
        return false;
    }
    if (s == NULL) {
        return false;
    }
    s->next = t->next;
    t->next = s;
    int temp = t->data;
    t->data = s->data;
    s->data = temp;
    
}
 

删除

//按位序删除

若要将第三个结点删除:只需将它的下一个结点存放的指针赋值给第二个结点即可

最后通过free函数释放掉要删除的结点的内存即可


bool ListDelete(LinkList& L, int i, int e) {  //将单链表中第i个结点删除
    if (i < 1) {
        return false;
    }
    int j = 0;
    LNode* K;
    K = L;
    //循环找到第i-1位的结点
    while (K!=NULL && j<i-1)  
    {   
        K = K->next;
        j++;
    }
    //判断 i-1位结点 是否存在以及 i位结点是否存在
    if (K == NULL|| K->next==NULL) {
        return false;
    }
    //创一个新的结点q,令其等于 要删除的第i位结点
    LNode* q;
    q = K->next;
    K->next = q->next;         //将i结点中存放下一位结点的指针赋值给 i-1结点
    e = q->data;               //提出删除结点的值
    free(q);                   //释放内存
    return true;
}

//按结点删除

若要将1结点删除,则将它的下结点的data和next复制到1结点即可

最后释放下节点。

//删除指定结点
bool  DeleteNode(LNode* p) {
    if (p == NULL) {
        return false;
    }
    LNode* q = p->next;
    p->data = p->next->data;
    p->next = q->next;
    free(q);
    return true;
}

 

**但如果要删除的结点是单链表中的最后一个结点,则会发生错误。

删除最后一个结点需要遍历整个单链表,同上。

总结:单链表不能逆向检索,有时会不太方便。

查找

1)按位查找

//单链表的查找
//单链表的按位查找
LNode * GetElem(LinkList & L, int i) {
    if (i < 1) {
        return NULL;
    }
    LNode * p;
    p = L;
    int j = 0;
    while (p != NULL && j < i)
    {
        p = p->next;
        j++;
    }
    return p;

}

2)按值查找与求表长

//按值查找
LNode* LocateElem(LinkList L, int e) {
    LNode* p = L;
    while (p != NULL && p->data != e)
    {
        p = p->next;

    }
    return p;
}
//求表长
int Length(LinkList L) {
    int len = 0;
    LNode* p = L;
    while (p != NULL)
    {
        p = p->next;
        len++;
    }
    return len;
}

单链表的建立

单链表的建立分为头插法和尾插法

一,尾插法创建单链表

//尾插法插入数据
LinkList TailInsert(LinkList& L) {          //用户输入创建单链表
    int x;
    L = (LinkList)malloc(sizeof(LNode));    //初始化空表
    LNode* s,* r = L;
    scanf("%d", &x);
    while (x != 999)  //输入999结束
    {
        s = (LinkList)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        r = s;
        scanf("%d", x);
    }
    r->next = NULL;
    return L;

 

 

 二,头插法建立单链表

 //头插法建立单链表
LinkList HeadInsert(LinkList& L) {
    LNode* s;
    int x;
    L = (LinkList)malloc(sizeof(LNode));
    L->next == NULL;   //防止内存 中的脏数据
    scanf("%d", &x);
    while (x != 9999)  //输入9999结束建立
    {
        s = (LinkList)malloc(sizeof(LNode));
        s->data = x;
        s->next = L->next;
        L->next = s;
        scanf("%d", x);
    }
    return L;
}

 

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

单链表的定义,插入与删除,查找,建立。 的相关文章

  • 如何使用带有进度条的 HttpClient 下载文件?

    我创建了一个名为SiteDownload并添加了一些下载图像的链接 using System Collections Generic using System Linq using System Net using System Threa
  • fork 和 exec 之间的区别

    两者有什么区别fork and exec 指某东西的用途fork and exec它体现了 UNIX 的精神 它提供了一种非常简单的方法来启动新进程 The fork调用基本上复制了当前进程 在almost任何方式 并非所有内容都会被复制
  • 如何在 C# 中启动文件

    编辑 我觉得自己像个白痴 我有一种感觉 像下面的答案会起作用 但没有看到任何与下面的答案类似的谷歌结果 所以当我看到这段复杂的代码时 我想它一定是这样的 我搜索并找到了这个Windows 列出并启动与扩展关联的应用程序 https stac
  • 以概率从列表中选择随机元素

    我有一个包含四个项目 A B C D 的列表 每个项目都有被选择的概率 例如 A 有 74 的机会被选中 B 15 C 7 D 4 我想创建一个函数 根据其概率随机选择一个项目 有什么帮助吗 为您的项目定义一个类 如下所示 class It
  • 析构函数、dispose 和 Finalize 方法之间的区别

    我正在研究垃圾收集器在 C 中的工作原理 我对使用感到困惑Destructor Dispose and Finalize方法 根据我的研究和理解 在我的类中拥有析构函数方法将告诉垃圾收集器以析构函数方法中提到的方式执行垃圾收集 该方法不能在
  • const_iterators 更快吗?

    我们的编码指南更喜欢const iterator 因为它们比正常的要快一点iterator 当您使用时 编译器似乎会优化代码const iterator 这真的正确吗 如果是的话 内部到底发生了什么使得const iterator快点 编辑
  • C语言中的array、&array、&array[0]有什么区别? [复制]

    这个问题在这里已经有答案了 在学习C语言中的数组和指针时 我很困惑 为什么ch ch ch 0 彼此相等 而sptr sptr sptr 0 却不相等 这是我的源代码 int main void char ch 7 1 2 3 4 5 6
  • 如何修改 edmx 的默认代码生成策略?

    我想修改默认的代码生成策略 该怎么做 我只是想修改类名 lt code Escape container gt to Entities并将默认连接字符串更改为name Default 我不想为该项目创建模板文件 我想编辑它以便它可以在全球范
  • C++20 views::join 在生成的嵌套范围::single_view 上进入无限循环

    我正在使用 GCC 实现 v10 2 和 v11 来处理 C 20 范围 测试的行为std views join https en cppreference com w cpp ranges join view 我尝试使用生成嵌套视图sin
  • 从 TFS 下载工作项附件(文件已损坏)

    我正在尝试创建 C 代码 因此我可以自动从 Team Foundation Server 下载 BUGS 预定义查询的所有附件 该代码似乎工作得很好 但所有下载的文件都因意外原因而损坏 我无法查看它们 有人可以看一下代码并分享意见吗 非常感
  • 将数组显式衰减为指针

    最简洁 最惯用的方式是什么明确地将数组衰减为指针 例如 考虑您需要能够指导 SFINAE 或明确过载的情况 template
  • 将纬度/经度转换为 X/Y,以便在美国地图图像上进行阿尔伯斯投影

    我正在尝试使用 C 或 Javascript 将纬度 经度转换为 X Y 坐标 以将带有 CSS 的 div 左 上 定位到美国地图的背景图像上 美国的标准地图投影是阿尔伯斯投影 如下所示 但 StackOverflow 仅提供参考基本墨卡
  • Roslyn,通过 hostObject 传递值

    我正在尝试通过 hostObject 发送一个类 但显然它不想工作 using Roslyn Compilers using Roslyn Compilers CSharp using Roslyn Scripting using Rosl
  • 如何将此 Boost ASIO 示例应用到我的应用程序中

    我已经阅读了很多 ASIO 示例 但我仍然对如何在我的应用程序中使用它们感到困惑 基本上 我的服务器端需要接受超过100个连接 客户端 这部分是通过使用线程池 通常每个CPU核心2 4个线程 来完成的 为简单起见 我们假设只有一个连接 为了
  • 我们可以使用 C# 录制发送到扬声器的声音吗

    我有一个软件 SoundTap Streaming Audio Recorder 它记录发送到扬声器的任何音频 无论流是来自网络还是来自某些文件或麦克风 我可以在桌面应用程序中制作这样的应用程序 以便我可以录制发送到扬声器的流 无论来源如何
  • 将 .NET 类库(主要定义 CRUD 操作)公开为服务

    公开现有内容的最佳 有效和最快的方法是什么 类 图书馆 主要定义 CRUD 操作 作为service 周转基金服务 or WCF数据服务 以便它可以与银光 or Ajax 在那儿tools 代码生成器 RAD 工具 哪些可以支持这个 预先感
  • 具有两个表的谓词构建器

    A Party可以有一个或多个Contact对象 我想选择全部Parties谁的街道名称包含特定关键字 如果我只想搜索Party我可以使用下面的代码 但我如何扩展它来搜索Contact public IQueryable
  • 返回右值 - 这段代码有什么问题? [复制]

    这个问题在这里已经有答案了 我遇到了以下代码片段 std string test std string m Hello return std move m int main std string m test 我知道上面的代码是不正确且不安
  • 使用 Powershell 或 C# 获取 Azure“文件和文件夹”作业状态

    我一直在尝试找到一种方法来获取在 AzureRM 中运行的几个客户上运行的 文件和文件夹 备份作业的状态 可以在 AzureRm 门户中手动找到状态 恢复服务保管库 gt 作业 gt 备份作业 使用powershell不显示任何作业信息 G
  • “while(true) { Thread.Sleep }”的原因是什么?

    我有时会遇到以下形式的代码 while true do something Thread Sleep 1000 我想知道这是否被认为是好的做法还是坏的做法以及是否有任何替代方案 通常我在服务的主函数中 找到 这样的代码 我最近在 Windo

随机推荐

  • SQL函数之聚合函数(求和,平均值,最大值,最小值,统计,取不重,取重)

    聚合函数 聚合函数对一组值进行计算并返回单一的值 通常聚合函数会与SELECT语句的GROUP BY子句一同使用 在与GROUP BY子句使用时 聚合函数会为每一个组产生一个单一值 而不会为整个表产生一个单一值 在这张数据表的基础上执行语句
  • Stable Diffusion WebUI部署过程踩坑记录

    概述 AI绘画十分火爆 博主最近在本地部署Stable Diffusion的时候遇到了一点问题 在查找解决办法的时候也是找了好几个不同的回答 但感觉都不全面 特在此记录一下自己遇到的问题 问题 Couldn t install gfpgan
  • 今晚8点直播

    近年来 聊天机器人技术及产品得到了快速的发展 聊天机器人作为人工智能技术的杀手级应用 发展得如火如荼 各种智能硬件层出不穷 本次公开课中 AI科技大本营联合电子工业出版社博文视点邀请到上海瓦歌智能科技有限公司总经理 狗尾草科技人工智能研究院
  • Sqlite如何修改表结构字段类型

    转自 Sqlite如何修改表结构字段类型 百度经验 baidu com SQLite 仅仅支持 ALTER TABLE 语句的一部分功能 我们可以用 ALTER TABLE 语句来更改一个表的名字 也可向表中增加一个字段 列 但是我们不能删
  • Java图书管理系统,课程设计必用(源码+文档)

    前提导入 高校图书馆是图书借阅的场所 它支撑着学校教学 科研等多项工作的开展 在高校中占有重要的位置 本文以高校图书馆的实际工作需求为导向 研发了一个能够满足图书管理人员和读者使用需求的图书管理系统 本系统采用Java MySQL 作为系统
  • 电容电感自谐振

    电感电容自谐振 MuRata 0603 仿真范围为0 30GHz 一 电感自谐振 二 电容自谐振 以上是利用ADS对muRata的实际电感电容自谐振的实验结果 该结果是根据阻抗幅度值得到的 其与S21显示的结果稍微有频偏 但能对应上 扼流电
  • springboot配置访问sqlserver,mysql数据库以及ssm的公共业务逻辑层抽取

    springboot的搭建 http blog csdn net goligory article details 78404480 最近喜欢用springboot 有时间就研究了一下 因为经常用sqlserver 在网上查了半天没有什么很
  • 【深度学习】Pytorch 系列教程(十一):PyTorch数据结构:3、变量(Variable)介绍

    目录 一 前言 二 实验环境 三 PyTorch数据结构 0 分类 1 张量 Tensor 2 张量操作 Tensor Operations 3 变量 Variable 一 前言 ChatGPT PyTorch是一个开源的机器学习框架 广泛
  • java web实验2客户端综合编程

    一 实验目的与要求 简述本次实验要求达到的目的 涉及到的相关知识点 实验的具体要求 1 实验目的 1 编写HTML网页 掌握HTML表单 表格等常用标签的使用 掌握CSS的语法和应用 2 编写JavaScript代码 熟悉并掌握JavaSc
  • ctk插件框架异常:The service interface class has no Q_DECLARE_INTERFACE macro

    ctk插件框架异常 The service interface class has no Q DECLARE INTERFACE macro 前言 当调试ctkPluginFramework时 抛出异常 throw ctkServiceEx
  • 【2022第十届‘泰迪杯’挑战赛】A题:害虫识别完整版(大致思路。详细过程和代码以及结果csv在压缩包中)

    2022第十届 泰迪杯 挑战赛 A题 害虫识别完整版 已有完整结果 2022泰迪杯挑战赛A题害虫识别完整版 大致思路 详细过程和代码在压缩包中 正式数据 2022 04 06 正式数据 提取码 u54n 写在前面 完整版下载 建议Chrom
  • ios备忘录下载安卓版_ios8备忘录app软件下载

    ios8备忘录最新版是一款可以在手机上安装ios8专用备忘录的软件 可以快速记录事件 支持语音输入 还可以合并多个便签 超多样式可以自己选择 感受全新的记录体验 软件的功能众多 还可以设置定时提醒功能 快来试试吧 ios8备忘录软件介绍 你
  • Latex

    http www tablesgenerator com 表格神器 LibreDigitalLibrary github io 印度人搜集的教育资源 1 MCM The Mathematical Contest in Modeling ht
  • java创建以任意图片为背景的窗口

    swing自带的窗体是不能够满足我们的应用需求的 所以需要制作任意图片和形状的JFrame框体 比如下图 并且可以设置窗体背景图片的透明度 下面说明如何做到上图的效果 1 首先你得需要一张好看的图片 比如羊皮纸 但是这个下载的图片是方方正正
  • 处理中文乱码

    处理传输中文乱码 String shopProductName request getParameter shopProductName if org springframework util StringUtils isEmpty sho
  • 雷达手势识别技术概述

    前言 不必害怕未知 无需恐惧犯错 做一个Creator 目录 前言 雷达技术特点 毫米波雷达 实现过程 手势信号预处理 手势特征提取与分类识别算法 雷达技术特点 随着雷达技术的快速发展和广泛应用 雷达手势识别已成为人机交互技术领域的一个重要
  • LoadRunner解决动态验证码问题

    对于这个问题 通常我们可以采取以下三个途径来解决该问题 1 第一种方法 也是最容易想到的 在被测系统中暂时屏蔽验证功能 也就是说 临时修改应用 无论用户输入的是什么验证码 都认为是正确的 这种方法最容易实现 对测试结果也不会有太大的影响 当
  • Linux命令之sync

    概述 sync 命令可以强制将内存中的文件缓冲写入磁盘 更新块信息 在 linux unix 系统中 在文件或数据处理过程中一般先放到内存缓冲区中 等到适当的时候再写入磁盘 以提高系统的运行效率 这样虽然可以提高磁盘写入数据的效率 但是也带
  • STM32高级定时器中心对齐PWM模式,频率设置的分享

    有关STM32高级定时器中心对齐PWM输出的实验记录 计算PWM的频率公式 f PCLK2 TIM Prescaler 1 TIM Period 1 2 条件TIM ClockDivision 0 而不是f PCLK2 TIM Presca
  • 单链表的定义,插入与删除,查找,建立。

    链表分为 单链表 双链表 循环链表 静态链表 一 单链表的定义 在内存空间中 各个节点在逻辑上相邻 但在物理上不相邻 在单个的结点内部需要存放 数据域 和 指针域 存放指向下一个结点的指针 优点 不要求一大片连续空间 改变容量方便 缺点 不