当前位置: 首页 > news >正文

数据结构--->单链表

文章目录

  • 链表
    • 链表的分类
  • 单链表
    • 单链表的存储结构
    • 单链表主要实现的接口函数
    • 单链表尾插
    • 动态申请新节点
    • 单链表头插
    • 单链表的尾删
    • 单链表的头删
    • 在指定位置之前插入
      • 单链表查找
      • 插入
    • 在指定位置之后插
    • 删除指定位置元素
    • 删除指定位置之后的元素
    • 顺序输出链表
    • 销毁单链表
  • 顺序表和单链表的区别
  • 关于指针传参

链表

链表是一种物理结构(储存结构)上不一定连续,不一定是顺序的存储结构,数据元素是通过链表中的指针链接次序实现的

链表的分类

image.png
链表有很多种类 两两匹配就一共有八种 这里主要介绍一下单链表(单向不带头不循环)

单链表

单链表的存储结构

图示

image.png
链表中的结点一般都是在堆上申请的,从堆上申请的空间,按照一定的规则申请的,两次申请的空间也能相同也可能不相同。用一个指针就能找到下一个结点的空间地址了,从而形成线性关系

typedef int ElemType;
typedef struct SListNode
{ElemType data;struct SListNode* next;
}SLTNode;typedef SLTNode* LinkList;//定义链表

定义一个数据域和指针域。数据域用来存放数据,指针域的指针指向下一个结点的空间地址

单链表主要实现的接口函数

//创建新结点
SLTNode* NewSLTNode(ElemType x);
//尾插
void SLTPushBack(SLTNode** phead, ElemType x);
//头插
void SLTPushFront(SLTNode** phead, ElemType x);
//尾删
void SLTPopBack(SLTNode** phead);
//头删
void SLTPopFront(SLTNode** phead);
//单链表查找
SLTNode* SLTNodeFind(SLTNode* phead, ElemType x);
//在pos之前插入
void SLTInsert(SLTNode** phead, SLTNode* pos, ElemType x);
//在pos之后插入
void SLTInsertAfter(SLTNode* pos, ElemType x);
//删除pos位置
void SLTErase(SLTNode** phead, SLTNode* pos);
//删除pos位置后得
void SLTEraseAfter(SLTNode* pos);
//打印
void SLTNodePrintf(SLTNode* ps);

单链表尾插

单链表插入主要分为两种情况

  • 没有结点,单链表是空的情况

image.png

  • 有一个以上的结点

image.png

注意:
这里需要一个头指针(pehad 指向第一个结点的指针)来维护这个链表。否则将无法寻找到这个链表

void SLTPushBack(SLTNode** phead, ElemType x)
{//申请结点SLTNode* newnode = NewSLTNode(x);//空链表if (*phead == NULL){*phead = newnode;}//有一个以上的结点else{SLTNode* tail = *phead;//遍历找最后一个结点while (tail->next != NULL){tail = tail->next;}//连接新结点tail->next = newnode;}
}

链表结点的类型是struct SListNode* (结构体指针)类型,插入一个新元素,需要改变头指针的指向,所以实参需要传其地址,形参需要一个结构体指针的指针才可接受这个地址即二级指针
每次进行插入操作时都要申请结点,封装成函数,方便复用

动态申请新节点

SLTNode* NewSLTNode(ElemType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if(newnode == NULL){perror("malloc fail");eixt(-1);}newnode->data = x;newnode->next = NULL;return newnode;
}

单链表头插

头插可以只看作一种情况
空和非空的处理结果都一样

图解
image.png
代码实现

void SLTPushFront(SLTNode** phead, ElemType x)
{//申请结点SLTNode* newnode = NewSLTNode(x);//空和非空链表都可处理newnode->next = *phead;*phead = newnode;
}

单链表的尾删

尾删要注意三种情况,分别是

  • 空链表
    错误处理
  • 只有一个结点
    直接释放该结点即可

image.png

  • 有两个结点以上的链表
    先找到最后一个结点,记录最后一个结点的前一个 然后释放最后一个结点,再将最后一个的前一个指针域置为NULL
    image.png

代码实现

void SLTPopBack(SLTNode** phead)
{//空链表assert(*phead);//只有一个结点if ((*phead)->next == NULL){free(*phead);*phead = NULL;}//有两个结点以上的链表else{SLTNode* tail = *phead;SLTNode* tailprev = NULL;//记录最后一个的前一个while (tail->next != NULL){tailprev = tail;tail = tail->next;}free(tail);tail = NULL;tailprev->next = NULL;}
}

单链表的头删

头删时要注意两种情况分别是

  • 空链表
    错误处理
  • 有一个或多个结点
    先将头指针移动到第二个结点(只有一个结点第二个结点即为NULL也符合逻辑)的位置,在释放该结点
    image.png

image.png
代码实现

void SLTPopFront(SLTNode** phead)
{//空assert(*phead);//一个和多个结点处理逻辑一样SLTNode* newhead = (*phead)->next;free(*phead);*phead = newhead;
}

在指定位置之前插入

位置由自己指定
比如链表元素 1 2 3 4 在2的位置之前插入6 链表变为1 6 2 3 4
插入之前首先要找到该元素结点的位置

单链表查找

SLTNode* SLTNodeFind(SLTNode* phead, ElemType x)
{assert(phead);SLTNode* pos = phead;while (pos){if (pos->data == x){return pos;}pos = pos->next;}//没有该元素return NULL;
}

然后根据查找到元素的结点位置进行插入

插入

在指定位置插入时要考虑以下情况

  • 空链表
    不需要做处理 因为空链表找不到指定的位置
  • 指定位置不存在
    错误处理
  • 指定的位置是第一个结点
    复用头插即可
  • 其他情况下插入
    申请新节点 找到pos的前一个结点 将新结点连接接起来
    image.png
void SLTInsert(SLTNode** phead, SLTNode* pos, ElemType x)
{assert(*phead);assert(pos);if (pos == *phead){SLTPushFront(phead, x);}else{//申请结点SLTNode* newnode = NewSLTNode(x);//找pos的前一个SLTNode* cur = *phead;SLTNode* posprev = NULL;while (cur != pos){posprev = cur;cur = cur->next;}posprev->next = newnode;newnode->next = pos;}
}

在指定位置之后插

比如链表元素 1 2 3 4 在2的位置之后插入6 链表变为1 2 6 3 4
和指定位置之前插入一样,首先要找到该元素结点的位置在进行插入
在指定位置后插入要考虑以下情况

  • 空链表
    不需要做处理 因为空链表找不到指定的位置
  • 指定位置不存在
    错误处理
  • 其他情况下插入

image.png
这里不用考虑插入的位置是最后一个结点的位置,这样首先要遍历链表进行判断,在复用尾插,代价太大。

代码实现

void SLTInsertAfter( SLTNode* pos, ElemType x)
{assert(pos);//申请新结点SLTNode* newnode = NewSLTNode(x);newnode->next = pos->next;pos->next = newnode;
}

删除指定位置元素

删除指定位置和插入指定位置一样,需要先查找到该元素结点的位置
比如链表元素 1 2 3 4 删除2的位置链表变为 1 3 4
删除pos位置要考虑以下情况

  • 空链表
    不需要做处理 因为空链表找不到指定的位置
  • 指定位置不存在
    错误处理
  • 指定位置是第一个结点
    复用头删
  • 其他情况下删除指定位置

image.png
代码实现

void SLTErase(SLTNode** phead, SLTNode* pos)
{//空链表assert(*phead);// 指定位置不存在assert(pos); //复用头删if (pos == *phead){SLTPopFront(phead);}else{//找pos前一个SLTNode* cur = *phead;SLTNode* prevpos = NULL;while (cur != pos){prevpos = cur;cur = cur->next;}prevpos->next = pos->next;free(pos);}
}

删除指定位置之后的元素

比如链表元素 1 2 3 4 删除2之后位置 链表变为 1 2 4
删除指定位置之后的元素分别要考虑以下情况

  • 空链表
    不需要做处理 因为空链表找不到指定的位置
  • 指定位置不存在
    错误处理
  • 是否是尾结点
    错误处理
  • 其他情况下删除指定位置之后

image.png
代码实现

void SLTEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* posnesxt = pos->next;pos->next = posnesxt->next;free(posnesxt);posnesxt = NULL;
}

顺序输出链表

void SLTNodePrintf(SLTNode* phead)
{SLTNode* tail = phead;while (tail != NULL){printf("%d " , tail->data);tail = tail->next;}printf("\n");
}

销毁单链表

void SLTNodeDestory(SLTNode** phead)
{assert(*phead);SLTNode* cur = *phead;SLTNode* curnext = NULL;while (cur != NULL){curnext = cur->next;free(cur);cur = curnext;}
}

顺序表和单链表的区别

不同点顺序表链表
存储空间上物理上一定连续逻辑上连续,物理上不一定连续
随机访问O(1)O(n)
任意位置插入或删除可能需要挪动数据,效率太低O(n)只需要修改指针指向即可
插入元素动态顺序表,空间不够时需要扩容没有容量概念,用多少申请多少
应用场景元素高效存储+频繁访问频繁在任意位置插入和删除

关于指针传参

当你传递一个参数给函数的时候,这个参数会不会在函数内被改动决定了函数参数形式

  • 如果需要改动,则需要传指向这个参数的指针
    比如单链表的头插,尾插、头删等,都需要改变头指针的指向位置,也就是这个参数需要被改动,那么传这个参数的指针
  • 如果不用被改动,可以直接传递这个参数
    比如单链表中的查找和打印,直接传参数就可以了,查找和打印,不用修改里面的内容

相关文章:

数据结构--->单链表

文章目录 链表链表的分类 单链表单链表的存储结构单链表主要实现的接口函数单链表尾插动态申请新节点单链表头插单链表的尾删单链表的头删在指定位置之前插入单链表查找插入 在指定位置之后插删除指定位置元素删除指定位置之后的元素顺序输出链表销毁单链表 顺序表和单链表的区…...

RT-Thread 线程间同步【信号量、互斥量、事件集】

线程间同步 一、信号量1. 创建信号量2. 获取信号量3. 释放信号量4. 删除信号量5. 代码示例 二、互斥量1. 创建互斥量2. 获取互斥量3. 释放互斥量4. 删除互斥量5. 代码示例 三、事件集1. 创建事件集2. 发送事件3. 接收事件4. 删除事件集5. 代码示例 简单来说,同步就是…...

B 树和 B+树 的区别

文章目录 B 树和 B树 的区别 B 树和 B树 的区别 了解二叉树、AVL 树、B 树的概念 B 树和 B树的应用场景 B 树是一种多路平衡查找树,为了更形象的理解。 二叉树,每个节点支持两个分支的树结构,相比于单向链表,多了一个分支。 …...

Go iota简介

当声明枚举类型或定义一组相关常量时,Go语言中的iota关键字可以帮助我们简化代码并自动生成递增的值。本文档将详细介绍iota的用法和行为。 iota关键字 iota是Go语言中的一个预定义标识符,它用于创建自增的无类型整数常量。iota的行为类似于一个计数器…...

PyQt6库和工具库QTDesigner安装与配置

锋哥原创的PyQt6视频教程: 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计12条视频,包括:2024版 PyQt6 Python桌面开发 视频教程(无废话版…...

性能测试:系统架构性能优化思路

今天谈下业务系统性能问题分析诊断和性能优化方面的内容。这篇文章重点还是谈已经上线的业务系统后续出现性能问题后的问题诊断和优化重点。 系统性能问题分析流程 我们首先来分析下如果一个业务系统上线前没有性能问题,而在上线后出现了比较严重的性能问题&#x…...

python字符串格式化

字符串格式化 # 2023年11月16日 星期四 y 2023 m 11 d 16 w 四 s %d年%d月%d日 星期%s%(y,m,d,w) print(s) s {}年{}月{}日 星期{}.format(y,m,d,w) print(s) s f{y}年{m}月{d}日 星期{w} print(s)...

Linux的基本指令(二)

目录 前言 学前补充 touch指令 mkdir指令 rmdir指令 rm指令 通配符* man指令 cp指令 mv指令(重要) 补充内容: 1、如何快速在Linux中写出代码 2、如何看待如此多的Linux指令 cat指令 前言 关于Linux的基本指令我们会分三到四篇文章进行分析&#xff0c…...

每日一题--寻找重复数

蝶恋花-王国维 阅尽天涯离别苦, 不道归来,零落花如许。 花底相看无一语,绿窗春与天俱莫。 待把相思灯下诉, 一缕新欢,旧恨千千缕。 最是人间留不住,朱颜辞镜花辞树。 目录 题目描述: 思路分析…...

C#,《小白学程序》第二十二课:大数的乘法(BigInteger Multiply)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// </summary> p…...

kafka,RabbitMQ,RocketMQ,他们之间的区别,架构,如何保证消息的不丢失,保证不重复消费,保证消息的有序性

文章目录 Kafka、RabbitMQ、RocketMQ 之间的区别是什么&#xff1f;性能数据可靠性服务可用性功能 RabbitMQ如何保证消息不丢失&#xff1f;Kafka 的架构说一下&#xff1f;Kafka 怎么保证消息是有序的&#xff1f;Kafka 怎么解决重复消费&#xff1f;Kafka 怎么保证消息不丢失…...

uni-app中vue3+setup实现下拉刷新、上拉加载更多效果

在小程序或各类app中&#xff0c;下拉刷新和上拉加载更多是极为常见和使用非常频繁的两个功能&#xff0c;通过对这两个功能的合理使用可以极大的方便用户进行操作。 合理的设计逻辑才能更容易挽留住用户&#xff0c;因为这些细节性的小功能点就变得极为重要起来。 那么在uni…...

微服务实战系列之Nginx(技巧篇)

前言 今天北京早晨竟然飘了一些“雪花”&#xff0c;定睛一看&#xff0c;似雪非雪&#xff0c;像泡沫球一样&#xff0c;原来那叫“霰”。 自然中&#xff0c;雨雪霜露雾&#xff0c;因为出场太频繁&#xff0c;认识门槛较低&#xff0c;自然不费吹灰之力&#xff0c;即可享受…...

好工具|datamap,一个好用的地图可视化Excel插件,在Excel中实现地理编码、拾取坐标

在做VRP相关研究的时候&#xff0c;需要对地图数据做很多处理&#xff0c;比如地理编码&#xff0c;根据“重庆市沙坪坝区沙正街174号”这样的一个文本地址知道他的经纬度&#xff1b;再比如绘制一些散点图&#xff0c;根据某个位置的经纬度在地图上把它标注出来。还有有的时候…...

Java——继承

继承是面向对象编程的三大特征之一&#xff0c;它让我们更加容易实现对已有类的扩展、更加容易实现对现实世界的建模。 继承有两个主要作用&#xff1a; 代码复用&#xff0c;更加容易实现类的扩展方便建模 继承的实现 继承让我们更加容易实现对类的扩展。比如我们定义了人…...

十、sdl显示yuv图片

前言 SDL中内置加载BMP的API&#xff0c;使用起来会更加简单&#xff0c;便于初学者学习使用SDL 如果需要加载JPG、PNG等其他格式的图片&#xff0c;可以使用第三方库&#xff1a;SDL_image 测试环境&#xff1a; ffmpeg的4.3.2自行编译版本windows环境qt5.12sdl2.0.22&…...

Docker Nginx容器部署vue项目

Docker Nginx容器部署vue项目 文章目录 Docker Nginx容器部署vue项目1. 前提2. 下载nginx镜像3. 编写nginx.conf配置文件4. 编写构建命令5. vue项目上传 1. 前提 Docker服务已部署 2. 下载nginx镜像 首先查看有没有nginx镜像 docker images没有的情况下再进行下载 docker …...

【深度学习】如何找到最优学习率

经过了大量炼丹的同学都知道&#xff0c;超参数是一个非常玄乎的东西&#xff0c;比如batch size&#xff0c;学习率等&#xff0c;这些东西的设定并没有什么规律和原因&#xff0c;论文中设定的超参数一般都是靠经验决定的。但是超参数往往又特别重要&#xff0c;比如学习率&a…...

详解—C++三大特性——多态

目录 一. 多态的概念 1.1 概念 二. 多态的定义及实现 2.1多态的构成条件 2.2 虚函数 2.3虚函数的重写 2.3.1虚函数重写的两个例外&#xff1a; 1. 协变(基类与派生类虚函数返回值类型不同) 2. 析构函数的重写(基类与派生类析构函数的名字不同) 2.4 C11 override 和 f…...

用idea搭建一个spring cloud微服务项目

以下是使用 IntelliJ IDEA 搭建 Spring Cloud 微服务项目的步骤&#xff1a; 创建一个新的 Maven 项目。 在 pom.xml 文件中添加以下依赖&#xff1a; <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-…...

【Hot 100 刷题计划】 LeetCode 215. 数组中的第K个最大元素 | C++ 快速选择与堆排序题解

LeetCode 215. 数组中的第K个最大元素 | C 快速选择与小顶堆双解法 &#x1f4cc; 题目描述 题目级别&#xff1a;中等 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不…...

2026届学术党必备的六大降AI率网站推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 使原本旨在降低文本被人工智能检测系统识别概率的降AI工具&#xff0c;借助调整词汇、句式以…...

突破ThinkPad散热限制:TPFanCtrl2智能风扇控制完全指南

突破ThinkPad散热限制&#xff1a;TPFanCtrl2智能风扇控制完全指南 【免费下载链接】TPFanCtrl2 ThinkPad Fan Control 2 (Dual Fan) for Windows 10 and 11 项目地址: https://gitcode.com/gh_mirrors/tp/TPFanCtrl2 ThinkPad笔记本以其稳定性和性能在专业用户中享有盛…...

效率提升利器:快马一键生成网络配置脚本与故障排查模拟环境

最近在准备计算机三级网络技术考试&#xff0c;发现手动搭建实验环境和编写配置脚本特别耗时。为了提升学习效率&#xff0c;我用InsCode(快马)平台开发了一个网络技术练习工具&#xff0c;分享下实现思路和使用体验。 核心功能设计 这个工具主要解决三个痛点&#xff1a;配置脚…...

Nginx性能优化-压缩

但很多开发者在配置nginx时容易混淆两个概念&#xff1a;Gzip动态压缩和Gzip静态压缩。本文将带你彻底搞懂这两者的区别、配置方法以及最佳实践。什么是Gzip动态压缩&#xff1f;原理&#xff1a; 当客户端&#xff08;浏览器&#xff09;发起请求时&#xff0c;Nginx接收到请求…...

SSN在LiDAR目标检测环境配置、SSN在LiDAR目标检测模型代跑训练、SSN在LiDAR目标检测模型改进创新SSN在LiDAR目标检测环境配置:Windows、Ubuntu、Centos、

SSN在LiDAR目标检测环境配置、 SSN在LiDAR目标检测模型代跑训练、 SSN在LiDAR目标检测模型改进创新 SSN在LiDAR目标检测环境配置&#xff1a;Windows、Ubuntu、Centos、Macos等系统环境&#xff0c;如果电脑拥有显卡&#xff0c;可配置GPU版本的SSN在LiDAR环境。 SSN在LiDAR目标…...

从PTA题目到项目实战:用Python和C语言两种思路重构‘插入排序’

从PTA题目到项目实战&#xff1a;用Python和C语言两种思路重构‘插入排序’ 算法学习常常陷入"纸上谈兵"的困境——我们能在OJ平台上AC题目&#xff0c;却难以将算法思想迁移到真实项目中。以插入排序为例&#xff0c;这道PTA基础题背后隐藏着数据处理、性能优化和语…...

深入STM32F407的UART Bootloader:除了烧程序,你还能用它做什么?

深入STM32F407的UART Bootloader&#xff1a;解锁系统级设计的五大高阶应用 当大多数开发者还在将UART Bootloader视为简单的固件烧录工具时&#xff0c;那些真正理解嵌入式系统设计精髓的工程师已经将其转化为产品全生命周期管理的核心组件。STM32F407芯片内置的Bootloader远…...

终极Win11优化指南:用Win11Debloat快速清理系统,性能提升70%

终极Win11优化指南&#xff1a;用Win11Debloat快速清理系统&#xff0c;性能提升70% 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to…...

Qwen3-0.6B-FP8从部署到应用:完整流程详解,新手必看

Qwen3-0.6B-FP8从部署到应用&#xff1a;完整流程详解&#xff0c;新手必看 你是不是刚接触AI模型&#xff0c;看着各种复杂的部署命令和配置就头疼&#xff1f;想快速体验一个能聊天、能推理、还能帮你写东西的智能助手&#xff0c;但又担心自己的电脑配置不够&#xff0c;或…...