速学数据结构 | 手把手教你会单链表的构建方式


在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥 个人专栏: 《初阶数据结构》《C语言进阶篇》

⛺️生活的理想,就是为了理想的生活!

文章目录

  • 📋 前言
  • 1. 什么是链表
    • 1.1 链表的物理结构
    • 1.2 链表的种类
  • 2. 链表的实现
    • 一. SList.h 单链表的声明
      • 3.1 定义链表结构
      • 3.2 单链表函数的声明
    • 二. SList.h 单链表的定义
      • 2.1 动态申请链表一个节点
      • 2.2 单链表打印
      • 2.3 单链表尾插
      • 2.4 单链表的头插
      • 2.5 单链表的尾删
      • 2.6 单链表头删
      • 2.7 单链表查找
      • 2.8 在pos之前插入x
      • 2.9 在pos之后插入x
      • 2.10 删除pos位置
      • 2.11 删除pos的后一个位置
    • 三. test.c 单链表的功能测试
  • 📝全篇总结

📋 前言

  🌈hello! 各位宝子们大家好啊!今天给大家带来的是初阶数据结构中单链表的构建方式,手把手教会你单链表
  ⛳️链表是指一种逻辑上是连在一起的数据结构,但是物理存储上却是分开的部分!是通过链表中的指针链接次序实现的一种数据结构!
  📚本期文章收录在《初阶数据结构》,大家有兴趣可以看看呐
  ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!

1. 什么是链表

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
在这里插入图片描述

顺序表我们都知道有点类似数组,是在物理上一块连续存放的内存块!所以顺序表也叫 线性表 但是开辟必须需要连续的空间空间的浪费特别严重!

  • 所以就有链表这种数据结构,避免了空间的浪费。
  • 链表在逻辑上是连在一起但是内存块确实分布在不同位置的
  • 通过指针访问每个链表的节点

1.1 链表的物理结构

在这里插入图片描述
从这里可以看出:

   链表在逻辑上是连续的但是,物理上是单独分开的。由每一块的指针记录下一个节点的地址进行访问

🔥 注意

  • 现实中的节点一般都是在堆上申请出来的
  • 在堆上申请的空间,是编译器按照一定规则分配的,俩次申请的空间可能有时连续有时不连续。

1.2 链表的种类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

  • 单向或者双向
    在这里插入图片描述

  • 带头或者不带头
    在这里插入图片描述

  • 循环或者非循环
    在这里插入图片描述

但是我们今天就先从简单的入手,先来实现一下单链表的结构!先从简单的下手。

  • 单链表结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

2. 链表的实现

好了废话不多讲,下面我们就来到链表的实现过程。链表前面我们了解了不是一个连续的存储结构,S是利用指针来进行每个节点的访问。

  • 注:我们把链表里的每个内容叫做一个节点

在这里插入图片描述

一. SList.h 单链表的声明

3.1 定义链表结构

链表链表首先我们要先定义链表的结构,链表既有数据又要和下一个链表联系起来那么肯定是要使用结构体:

  • 来定义链表
  • 而内容需要一个 data 和 指向下一个节点的指针!
typedef  int  SLTDataType;
//定义链表结构
typedef	struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;

3.2 单链表函数的声明

单链表要实现的功能其实也非常简单,和顺序表是一模一样的。增删改查等这些操作而我们只要把这些函数实现了,那么在刷关于链表的题的时候也就无非是这些操作的变形。

  • 下面我们就来看看单链表具体要实现的功能把!
//动态申请链表节点
SLTNode* BuySListNode(SLTDataType x);//打印单链表
void SLTPrint(SLTNode* plist);//单链表头插
void SLTPushFront(SLTNode** pplist,SLTDataType x);//单链表尾插
void SLTPushBack(SLTNode** pplist, SLTDataType x);//单链表头删
void SLTPopFront(SLTNode** pplist);//单链表尾删
void SLTPopBack(SLTNode** pplist);//查找节点
SLTNode* SLTFind(SLTNode* pplist, SLTDataType x);//在pos以前插入x
void SLTInsert(SLTNode** pplist, SLTNode* pos, SLTDataType x);// 在pos以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x);// 删除pos位置
void SLTErase(SLTNode** pplist, SLTNode* pos);// 删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos);// 单链表的销毁
void SListDestroy(SLTNode* pplist);

二. SList.h 单链表的定义

2.1 动态申请链表一个节点

前面我们把链表的基本结构定义好了那么接下来就申请节点了,这样我们才能进行链表的链接已经数据的存储!

  • 而开辟节点直接用 malloc 开辟空间然后赋值就好啦!
//动态申请链表节点
SLTNode* BuySListNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc file");exit(-1);}newnode->data = x;newnode->next = NULL;return newnode;
}

2.2 单链表打印

打印单链表也是一个十分简单的功能了,既然我们链表的每个节点的 next 存储的都是下一个节点那么直接循环访问就好啦!

  • 要注意控制好循环变量的结束条件
  • 和链表最后 NULL 的打印
//打印单链表
void SLTPrint(SLTNode* plist)
{SLTNode* cur = plist;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}

2.3 单链表尾插

单链表的尾插也不是很难控制好着俩点就好了:

  • 第一个是 plist 为空的情况,直接尾插
  • 第二个是 plist 不为空的情况,循环找到尾直接尾插
//单链表尾插
void SLTPushBack(SLTNode** pplist, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);if (*pplist == NULL){*pplist = newnode;}else{SLTNode* tail = *pplist;while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}
}

2.4 单链表的头插

这个可以说是最简单的部分了,只要让要 plist 指向 插入的节点,插入节点的 next 指向下一个节点。

  • 还要注意一下断言
//单链表头插
void SLTPushFront(SLTNode** pplist,SLTDataType x)
{SLTNode* newnode = BuySListNode(x);newnode->next = *pplist;*pplist = newnode;
}

2.5 单链表的尾删

单链表的头插尾插我们实现了下面就是单链表的尾删了。注意要控制好边界的几种情况就好了

  • 一个是链表只有一个节点的情况下直接删除
  • 还有一个是链表有多个节点需要遍历
//单链表尾删
void SLTPopBack(SLTNode** pplist)
{//非空判断assert(*pplist);SLTNode* tail = *pplist;if ((*pplist)->next == NULL){free(*pplist);*pplist = NULL;}else{while (tail->next->next != NULL){tail = tail->next;}free(tail->next);tail->next = NULL;}}

2.6 单链表头删

单链表的头删注意考虑俩总情况,一个是只有一个节点释放,一个是多个节点释放。

  • 在 assert 断言一下NULL链表就不删除
//单链表头删
void SLTPopFront(SLTNode** pplist)
{//非空判断assert(*pplist);SLTNode* newhead = (*pplist)->next;free(*pplist);*pplist = newhead;
}

2.7 单链表查找

为什么要先写单链表的查找呢,因为我们现实中通常不知道我们要删除或者插入的数在第一个点上所以需要先查找要删除或者插入的数到时候删除直接复用就好了。

  • 查找的话直接循环遍历就好了,如果找不到就返回空NULL。
//查找节点
SLTNode* SLTFind(SLTNode* plist, SLTDataType x)
{SLTNode* cur = plist;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

2.8 在pos之前插入x

和前面的删除一样,需要控制好不同的情况和 暴力检测一下 plist 传过来的是不是一个空指针。

  • 空指针就直接退出说明传错了
  • 还要注意遍历pos前一个节点
//在pos以前插入x
void SLTInsert(SLTNode** pplist, SLTNode* pos, SLTDataType x)
{assert(*pplist);assert(pos);if (pos == *pplist){SLTPushFront(pplist,x);}else{SLTNode* prev = *pplist;while (prev->next != pos){prev = prev->next;}SLTNode* newnode = BuySListNode(x);prev->next = newnode;newnode->next = pos;}
}

2.9 在pos之后插入x

这个就没在pos之前插入x那么复杂了可以根据指针找到下一个节点,然后删除pos的后一个节点

  • 将next 连接到pos的下下个节点上
// 在pos以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);if (pos->next == NULL){pos->next = newnode;}else{SLTNode* next = pos->next->next;pos->next = newnode;newnode->next = next;}
}

2.10 删除pos位置

删除pos的位置就需要循环遍历pos,的前一个位置。然后进行 free 释放空间

  • 在把俩个节点关联起来就可以了

// 删除pos位置
void SLTErase(SLTNode** pplist, SLTNode* pos)
{assert(pplist);assert(pos);if(*pplist == pos){SLTPopFront(pplist);}else{SLTNode* prve = *pplist;while (prve->next != NULL){prve = prve->next;}prve->next = pos->next;free(pos);}
}

2.11 删除pos的后一个位置

// 删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* posNext = pos->next;pos->next = posNext->next;free(posNext);posNext = NULL;}

三. test.c 单链表的功能测试

这里博主就不给大家测试给大家写个样例,大家自己去试试增删查改哦!

void Test_SList2()
{SLTNode* plist = NULL;SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPushFront(&plist, 5);SLTPrint(plist);
}
int main()
{Test_SLsit1();}

📝全篇总结

✅ 归纳:
好了以上就是关于分支语句 链表 的所有知识点了,大家快下去练习练习吧!
  链表的介绍
  链表的结构
  链表的增删查改

☁️ 把本章的内容全部掌握,铁汁们就可以熟练应用switch语句啦!
看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。
在这里插入图片描述

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

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

相关文章

React antd Table点击下一页后selectedRows丢失之前页选择内容的问题

一、问题 使用了React antd 的<Table>标签&#xff0c;是这样记录选中的行id与行内容的&#xff1a; <TabledataSource{data.list}rowSelection{{selectedRowKeys: selectedIdsInSearchTab,onChange: this.onSelectChange,}} // 表格是否可复选&#xff0c;加 type: …

智慧公厕:将科技融入日常生活的创新之举

智慧公厕是当今社会中一项备受关注的创新项目。通过将科技融入公厕设计和管理中&#xff0c;这些公厕不仅能够提供更便利、更卫生的使用体验&#xff0c;还能够极大地提升城市形象和居民生活质量。本文将以智慧公厕领先厂家广州中期科技有限公司&#xff0c;大量的精品案例项目…

vue3中使用return语句返回this.$emit(),在同一行不执行,换行后才执行,好奇怪!

今天练习TodoList任务列表案例,该案例效果如图所示&#xff1a; 此案例除了根组件App.vue&#xff0c;还有TodoList、TodoInput、TodoButton三个子组件。 因为有视频讲解&#xff0c;在制作TodoList、TodoInput时很顺利&#xff0c;只是在完成TodoButton这个组件时出了点问题…

网络爬虫——urllib(1)

前言&#x1f36d; ❤️❤️❤️网络爬虫专栏更新中&#xff0c;各位大佬觉得写得不错&#xff0c;支持一下&#xff0c;感谢了&#xff01;❤️❤️❤️ 前篇简单介绍了什么是网络爬虫及相关概念&#xff0c;这篇开始讲解爬虫中的第一个库——urllib。 urllib&#x1f36d; …

UG\NX二次开发 用程序修改“用户默认设置”

文章作者:里海 来源网站:《里海NX二次开发3000例专栏》 感谢粉丝订阅 感谢 wuguoyana、duanxheng 两位粉丝订阅本专栏,非常感谢。 简介 可以用程序修改“用户默认设置”吗?下面是用代码修改“用户默认设置->基本环境->用户界面->操作记录->操作记录语言”的例子…

【Python+requests+unittest+excel】实现接口自动化测试框架

一、框架结构&#xff1a; 工程目录 二、Case文件设计 三、基础包 base3.1 封装get/post请求&#xff08;runmethon.py&#xff09; 1 import requests2 import json3 class RunMethod:4 def post_main(self,url,data,headerNone):5 res None6 if header …

【AI视野·今日Robot 机器人论文速览 第四十六期】Tue, 3 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 3 Oct 2023 Totally 76 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;Aerial Interaction with Tactile, 无人机与触觉的结合&#xff0c;实现空中交互与相互作用。(from CMU) website&#…

10.3倒水问题(几何图论建模)

坐标图中每一个位置都对应一个合法的状态&#xff0c;BC对5升杯子做出限制&#xff0c;AD对9升杯子作出限制 每次倒水&#xff0c;都只能把目标杯子装满&#xff0c;否则无法确定倒出水的多少与目标杯子此时水的容量 所以例如&#xff0c;倒5升杯子时&#xff0c;只能要么把5…

Python逐日填补Excel中的日期并用0值填充缺失日期的数据

本文介绍基于Python语言&#xff0c;读取一个不同的列表示不同的日期的.csv格式文件&#xff0c;将其中缺失的日期数值加以填补&#xff1b;并用0值对这些缺失日期对应的数据加以填充的方法。 首先&#xff0c;我们明确一下本文的需求。现在有一个.csv格式文件&#xff0c;其第…

Pyhon-每日一练(1)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

竞赛选题 深度学习 opencv python 实现中国交通标志识别_1

文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 &#x1f525; 优质…

拆解常见的6类爆款标题写作技巧!

究竟是先写好文章再拟标题还是先确定标题再写文章呢&#xff1f;很多写稿小白都会有这样的疑惑。 在“人人皆可新媒体”的时代&#xff0c;公众号推文类型琳琅满目&#xff0c;每个人都可以建立自己的公众号&#xff0c;写出自己想写的文章。 但怎样起标题、起什么样的标题&a…

Linux CentOS7 vim宏操作

vim的macro就是用来解决重复的问题。在vim寄存器的文章里面已经对macro有所涉及&#xff0c;macro的操作都是以文本的方式存放在寄存器中。 宏是一组命令的集合&#xff0c;应用极其广泛&#xff0c;包括MS Office中的word编辑器&#xff0c;excel编辑器和各种文本编辑器&…

MySQL复制,约束条件,查询与安全控制

MySQL之复制 复制表 我有一个表 mysql> show tables; ------------------ | Tables_in_school | ------------------ | student | ------------------mysql> select * from student; -------------------------------------------- | id | name | sec |…

asp.net班级管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net班级管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 asp.net班级管理系统 二、功能介绍 1…

LVS负载均衡集群

一.LVS集群基本介绍 1.1.群集的含义 Cluster&#xff0c;集群、群集 由多台主机构成&#xff0c;但对外只表现为一个整体&#xff0c;只提供一个访问入口&#xff08;域名或IP地址&#xff09;&#xff0c;相当于一台大型计算机。 1.2.群集的作用 对于企业服务的的性能提升…

【Spring篇】Bean的三种配置和实例化方法

&#x1f38a;专栏【Spring】 &#x1f354;喜欢的诗句&#xff1a;天行健&#xff0c;君子以自强不息。 &#x1f386;音乐分享【如愿】 &#x1f384;欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f33a;bean基本配置&#x1f33a;bean别名配置&#x1f33a…

2023 年 Web 安全最详细学习路线指南,从入门到入职(含书籍、工具包)【建议收藏】

第一个方向&#xff1a;安全研发 你可以把网络安全理解成电商行业、教育行业等其他行业一样&#xff0c;每个行业都有自己的软件研发&#xff0c;网络安全作为一个行业也不例外&#xff0c;不同的是这个行业的研发就是开发与网络安全业务相关的软件。 既然如此&#xff0c;那其…

【智能家居项目】裸机版本——字体子系统 | 显示子系统

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《智能家居项目》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 今天实现上图整个项目系统中的字体子系统和显示子系统。 目录 &#x1f004;设计思路&#x1…

解决报错: require is not defined in ES module scope

用node启动mjs文件报错&#xff1a;require is not defined in ES module scope 现象如下&#xff1a; 原因&#xff1a; 文件后缀是mjs, 被识别为es模块&#xff0c;但是node默认是commonjs格式&#xff0c;不支持也不能识别es模块。 解决办法&#xff1a;把文件后缀从.mjs改…