【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能

在这里插入图片描述

君兮_的个人主页

勤时当勉励 岁月不待人

C/C++ 游戏开发

Hello,米娜桑们,这里是君兮_,我们接着之前讲过的顺序表来继续介绍初阶数据结构的内容,今天给大家带来的是有关链表的基本知识和各种接口功能的实现
好了,废话不多说,开始今天的学习吧!

链表

  • 一.链表的基础知识
    • 1.链表的概念与基本结构
    • 2.链表的分类
  • 二.无头单链表的实现
    • 1.初始化链表 BuySListNode
    • 2.打印链表 SLTPrint
    • 3.头插 SLTPushFront与头删 SLTPopFront
      • 头插
      • 头删
    • 4.尾插SLTPushBack和尾删 SLTPopBack
      • 尾插
      • 尾删
  • 总结

一.链表的基础知识

1.链表的概念与基本结构

  • 概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
  • 链表链表,表如其名,链表的结构就如同被连接起来了,只不过在中间连接链表的“绳索”是指针。
    在这里插入图片描述
  • 从基本结构图中我们可以看出:
    1.链式结构在逻辑上是连续的,但与顺序表不同,在物理上链表是不一定连续的
    2.现实中,链表的节点一般都是从堆上申请出来的。
    3.从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续。

2.链表的分类

  • 在实际中链表的结构非常多样,下面就简单的介绍几种
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  • 虽然链表有多种结构,但是最常用的还是这两种
    在这里插入图片描述
  • 1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
  • 2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我也会带大家逐一实现代码。

二.无头单链表的实现

  • 由于我们是初阶数据结构,且这是有关链表的第一篇博客,我们就先从最简单的无头单链表开始实现。
  • 首先我们先把需要的几个功能的接口列出来然后咱们来一个一个介绍。

说明:以下包括后面的所有代码的函数名称等都是我根据该函数的功能编的,也就是说这些函数名等不唯一,你也可以起别的名字,不影响链表的使用,但就像给孩子取名一样,我们都不希望我们的孩子的名字叫狗蛋,二狗子什么的,实际上,在函数的命名中你瞎起名字就和这些差不多,因此我建议无论是现在还是以后的函数的命名最好都按照功能来命名,这样既增加了代码的可读性,也让人一看便知各个函数的功能。

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode
{SLTDataType Data;struct SListNode * next;}SLTNode;
//打印链表
void SLTPrint(SLTNode* phead);
//初始化链表
SLTNode* BuySListNode(SLTDataType x);
void SLTPushBack(SLTNode** pphead, SLTDataType x);
void SLTPushFront(SLTNode** pphead, SLTDataType x);void SLTPopBack(SLTNode** pphead);
void SLTPopFront(SLTNode** pphead);
// 找某个数
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);// 在pos之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);// 在pos以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x);// 删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos);// 删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos);
//修改pos位置的值
void SLTModify(SLTNode**pphead, SLTNode* pos, SLTDataType x);
// 单链表的销毁
void SListDestroy(SLTNode** pphead);
  • 注意:对接口的声明都包含在头文件中
  • 先讲一下这里面需要注意的几个地方:
  • 1.第一处的 typedef 实际是为了方便我们的使用,因为我们也不知道我们的链表是用来存储什么类型的数据的,因此我们这里就定义一个SLDataType,下面的代码中统一把数据类型用它来代替,这样一来,我们以后想要改变存储的数据类型,只需要改动这里即可,比如我们现在想要存储double类型的数据
typedef double SLDataType;
  • 2.关于我们的链表的结构体
typedef struct SListNode
{SLTDataType Data;struct SListNode * next;}SLTNode;
  • 我们说了,我们的链表的连接是通过指针来实现的,因此我们的结构体中第一个成员是该节点存储的值,第二个成员则是一个该结构体的指针,指向的是下一个节点的地址。

1.初始化链表 BuySListNode

  • 当我们想使用我们的链表时,首先就像变量一样需要先把它初始化一下
//初始化链表
SLTNode* BuySListNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc failed:");exit(-1);}newnode->Data = x;newnode->next = NULL;return newnode;}
  • 我们首先通过malloc为我们链表的一个节点开辟了空间,然后通过perror判断了我们的malloc是否成功,如果成功,我们就把该链表的值置为我们输入的x,由于此时只有它一个节点,因此next置空,这样我们的一个节点就初始化好了。

2.打印链表 SLTPrint

  • 当我们初始化成功后,我们就想把我们的链表打印一下,看看我们的链表是否成功初始化了,因此我们继续来写打印链表的函数
//打印链表
void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur){printf("%d->", cur->Data);cur = cur->next;}printf("NULL\n");
}
  • 我们定义了一个结构体指针cur指向传入的链表的表头,当cur不为空时,我们就打印一下此时该节点中的Data,并通过next找到下一个节点
  • 由于我们链表的最后一个元素是NULL,因此我们最后把链表中所有节点都打印完后,在最后再补上一个NULL。

在这里插入图片描述

  • 效果如上图

3.头插 SLTPushFront与头删 SLTPopFront

  • 头插与头删顾名思义,就是在链表表头插入节点或者删除链表表头的节点

头插

//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);newnode->next = *pphead;*pphead = newnode;
}
  • 头插的逻辑图是这样的
    在这里插入图片描述
    在这里插入图片描述

头删

//头删
void SLTPopFront(SLTNode** pphead)
{//空assert(*pphead);//非空;SLTNode* newhead = (*pphead)->next;//保存一下下一个节点的地址free(*pphead);*pphead = newhead;
}
  • 头删的逻辑图
  • 首先先判断*pphead是否为空,如果为空,说明这个链表压根不存在
    在这里插入图片描述
    在这里插入图片描述

4.尾插SLTPushBack和尾删 SLTPopBack

  • 与前面同理,尾插和尾删是作用于链表的最后的

尾插

//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);SLTNode* tail = *pphead;//链表中没有节点时if (*pphead == NULL){*pphead = newnode;}else{//不为空时while (tail->next){tail = tail->next;}tail->next = newnode;}
}
  • 我们知道链表的最后一个节点的next存放的地址为空,我们来通过逻辑图分析一下
  • 首先还是特殊情况,当我们的链表中没有节点时,那我们就把头指针直接指向需要插入的节点就行。
    在这里插入图片描述
    在这里插入图片描述

尾删

//尾删
void SLTPopBack(SLTNode** pphead)
{//为空assert(*pphead);//只有一个节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}//不为空且有多个节点else{SLTNode* tail = *pphead;while (tail->next->next){tail = tail->next;}free(tail->next);tail->next = NULL;}
}
  • 还是先来分析特殊情况,先通过assert断言来判断一下该链表是否为空,其次,如果这个链表只有一个节点时,我们指向把该节点free释放掉再置空即可,不需要其他操作。
  • 一般情况的逻辑图
    在这里插入图片描述
    在这里插入图片描述

总结

  • 由于篇幅有限,今天的内容到这里就结束了,之后我们会把剩下没讲的接口讲完然后再带大家做几道oj题让大家更加熟悉链表的使用。相信如果你能一直跟着坚持下去那么你链表这一块的初阶知识就一定没什么问题啦!切记要自己上手敲敲代码哦!

  • 好了,如果你有任何疑问欢迎在评论区或者私信我提出,大家下次再见啦!

新人博主创作不易,如果感觉文章内容对你有所帮助的话不妨三连一下这个新人博主再走呗。你们的支持就是我更新的动力!!!

**(可莉请求你们三连支持一下博主!!!点击下方评论点赞收藏帮帮可莉吧)**

在这里插入图片描述

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

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

相关文章

LeetCode 周赛上分之旅 # 36 KMP 字符串匹配殊途同归

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…

day50-Insect Catch Game(捉虫游戏)

50 天学习 50 个项目 - HTMLCSS and JavaScript day50-Insect Catch Game&#xff08;捉虫游戏&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport"…

codeblocks编译lvgl报错

codeblocks编译lvgl报错 1.报错内容2.解决方案3.lvgl本身代码报错 1.报错内容 error: unknown type name _In_opt_ ...2.解决方案 官网下载&#xff1a; 这里的Compiler’s installation directory 选择自带的 3.lvgl本身代码报错 undefined reference to _lv_utils_bse…

面试总结-Redis篇章(九)——Redis主从复制、主从数据同步原理

Redis其他面试问题 主从复制单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写分离主节点主要进行客户端的写操作&#xff0c;从节点进行客户端的读操作&#xff0c;因为Redis一直都是读多写少&…

UE5.1.1 创建C++项目失败

因一直使用Unity开发环境&#xff0c;安装Unreal后&#xff0c;并未详细配置过其开发环境&#xff0c;默认创建蓝图工程无异常&#xff0c;但创建UE C项目时总共遇到两个错误&#xff1a; 错误一 Running /Epic/UE/UE_5.1/Engine/Build/BatchFiles/Build.bat -projectfiles -…

<C++>二、类和对象-构造函数

1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生…

【Linux多线程】死锁问题介绍

死锁 &#x1f96d;什么是死锁&#x1f965;死锁产生的条件&#x1f95d;如何避免死锁&#x1f345; 避免死锁算法 &#x1f96d;什么是死锁 死锁是多线程或多进程编程中的一种常见问题&#xff0c;指的是两个或多个线程&#xff08;或进程&#xff09;相互等待对方持有的资源&…

搜索二叉树_SearchBinaryTree

目录 搜索二叉树的原理 搜索二叉树的搜索时间复杂度 二叉搜索树实现_key 模型 节点 构造函数 查找 中序遍历 插入 循环 递归 删除 循环 1.删除叶子节点 2.删除有一个孩子的节点 3.左右孩子都不为空 递归 析构函数 拷贝构造 operator key_value 模型 节点 …

Mysql触发器

1.触发器 触发器是与表有关的数据库对象&#xff0c;指在 insert / update / delete 之前或之后&#xff0c;触发并执行触发器中定义的SL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性&#xff0c;日志记录&#xff0c;数据校验等操作。 使用别名 OLD 和 …

mysql安装教程保姆级

MySQL免安装本地运行 1.下载MySQL2.创建install.bat3.init.sql 初始创建4.环境变量配置5.运行 install.bat 管理员权限运行6.连接成功遇到的问题 1.下载MySQL ①地址&#xff1a;https://downloads.mysql.com/archives/community/ ②解压 2.创建install.bat 放在mysql>b…

算法综合篇专题一:双指针问题

"就算没有看清那株灿烂的花蕊&#xff0c;也应该放声歌颂赞美鲜红的玫瑰" 1、移动零 (1) 题目解析 (2) 算法原理 class Solution { public:void moveZeroes(vector<int>& nums) {for(int cur0,dest-1;cur<nums.size();cur){if(nums[cu…

java设计模式-建造者(Builder)设计模式

介绍 Java的建造者&#xff08;Builder&#xff09;设计模式可以将产品的内部表现和产品的构建过程分离开来&#xff0c;这样使用同一个构建过程来构建不同内部表现的产品。 建造者设计模式涉及如下角色&#xff1a; 产品&#xff08;Product&#xff09;角色&#xff1a;被…

前端工程化最佳实践:项目结构、代码规范和文档管理

文章目录 前端工程化最佳实践项目结构设计与组织文档管理和注释规范国际化和本地化实践 前端工程化的未来发展趋势前端工程化领域的最新技术和工具WebAssembly 和前端性能优化可持续性和可访问性的趋势 总结前端工程化的关键知识点前端工程化对项目和团队的价值 前端工程化最佳…

《golang设计模式》第一部分·创建型模式-01-单例模式(Singleton)

文章目录 1. 概述1.1 目的1.2 实现方式 2. 代码示例2.1 设计2.2 代码 1. 概述 1.1 目的 保证类只有一个实例有方法能让外部访问到该实例 1.2 实现方式 懒汉式 在第一次调用单例对象时创建该对象&#xff0c;这样可以避免不必要的资源浪费 饿汉式 在程序启动时就创建单例对象…

卷积神经网络

目录 注意&#xff1a;有参数计算的才叫层 1.应用 1.1分类和检索 1.2超分辨率重构 1.3医学任务 1.4无人驾驶 1.5人脸识别 2.卷积 2.1卷积神经网络和传统网络的区别 2.2整体框架 2.3理解卷积&#xff08;重点&#xff09; 2.4为何要进行多层卷积 2.5卷积核的参数 2.6…

C++STL库中的list

文章目录 list的介绍及使用 list的常用接口 list的模拟实现 list与vector的对比 一、list的介绍及使用 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2. list的底层是双向带头循环链表结构&#xff0c;双向带头循…

基于ssm+mysql+jsp高校疫情防控出入信息管理系统

基于ssmmysqljsp高校疫情防控出入信息管理系统 一、系统介绍二、功能展示1.登陆2.教师管理3.学生管理4.打卡记录管理5.学生申请通行证6.通行证管理7.留言信息管理8.公告类型管理9.公告管理 四、获取源码 一、系统介绍 学生 : 个人中心、打卡记录管理、学生申请通行证、通行证管…

<C++> STL_string

目录 1.string类 2.string类的接口 2.1 成员函数 2.1.1 string构造函数 2.1.2 string赋值运算 2.1.3 string析构函数 2.2 string对象访问以及迭代器 2.2.1 string的遍历方式 2.2.2 迭代器的使用 2.2.3 const_迭代器的使用 2.2.4 at 2.2.5 back和front 2.3 string容…

Docker基础命令(一)

Docker使用1 一、运行终端 打开终端&#xff0c;输入docker images &#xff0c;如果运行正常&#xff0c;表示docker已经可以在本电脑上使用了 二、docker常用命令 指令说明docker images查看已下载的镜像docker rmi 镜像名称:标签名删除已下载的镜像docker search 镜像从官…

Java如何实现将类文件打包为jar包

目录 将类文件打包为jar包 1.写类文件2.编译3.测试4.打jar包jar包应该怎么打&#xff1f; 1.首先确保你的项目2.选中你的项目,点右键3.选择runnable jar file4.如下图,直接看图5.然后点finish 将类文件打包为jar包 为实际项目写了一个工具类&#xff0c;但是每次使用时都需要…