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

数据结构--单链表 详解(附代码

目录:

1:链表的概念及结构
2:实现单链表
3:常见疑问 解答 (看到最后!!)

一:链表的概念及结构

1.1 概念:
 链表是⼀种 物理存储结构上非连续、非顺序的 存储结构,但在 逻辑上是连续的 ,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
1.2 结构:
链表的结构跟火车车厢相似,淡季时车次的车厢会相应减少,旺季时车次的车厢会额外增加几节。只需要将火车里的某节车厢去掉/加上,不会影响其他车厢,每节车厢都是独立存在的。
---在链表里,每节“车厢”是什么样的呢?
与顺序表不同的是,链表里的每节"车厢"都是 独立申请下来的空间,我们称之为“结点/节点”
节点的组成主要有两个部分:
 当前节点要保存的数据下⼀个节点的地址(指针变量)
注意:链表中的最后一个节点的next指向空指针(next=NULL)
图中指针变量 plist保存的是第⼀个节点的地址,我们称plist此时“指向”第⼀个节点,链表中的每个节点都是独立申请的(即需要插⼊数据时才去申请⼀块节点的空间),我们需要通过指针变量来保存下⼀个节点位置才能从当前节点找到下⼀个节点。
结合前面学到的结构体知识,我们可以给出每个节点对应的结构体代码:
假设当前保存的节点为整型:
struct SListNode
{int data;    //节点数据struct SListNode* next; //指向下⼀个节点的指针
};
二:实现单链表
单链表英文名——single linked list,我们简写为SL
1.1创建
为了养成模块化好习惯,我们把代码分开来写
1.2 链表的功能
1.3链表的实现
SList.h
#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);//打印
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);
//在指定位置之前插⼊数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos);
//在指定位置之后插⼊数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos);
//销毁链表
void SListDesTroy(SLTNode** pphead);

SList.c

#include"SList.h"void SLTPrint(SLTNode* phead)//打印
{SLTNode* pcur = phead;while (pcur)//pcur!=NULL{printf("%d->",pcur->data);pcur = pcur->next;}printf("NULL\n");
}SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if(newnode==NULL){perror("newnode fail");exit(1);}newnode->data = x;newnode->next = NULL;return newnode;
}//一级指针的地址用      
void SLTPushBack(SLTNode** pphead, SLTDataType x)//二级指针来接收
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);//空链表 与 非空链表if (*pphead == NULL)//*pphead就是指向第一个节点的指针{*pphead = newnode;}else{SLTNode* ptail = *pphead;//先找到尾节点while (ptail->next)//!=NULL{ptail = ptail->next;}//ptail指向的就是尾节点ptail->next = newnode;}
}
void SLTPushFront(SLTNode** pphead, SLTDataType x)//头插
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}
void SLTPopBack(SLTNode** pphead)//尾删
{assert(*pphead && pphead);//一个节点if ((*pphead)->next == NULL)// ->的优先级高于*{free(*pphead);*pphead = NULL;}//多个节点else{SLTNode* ptail = *pphead;SLTNode* prev = *pphead;while (ptail->next){prev = ptail;ptail = ptail->next;}free(ptail);ptail = NULL;prev->next = NULL;}
}
void SLTPopFront(SLTNode** pphead)//头删
{assert(*pphead && pphead);SLTNode* next = (*pphead)->next;// ->的优先级高于*free(*pphead);*pphead = next;
}
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{assert(phead);SLTNode* pcur = phead;while (pcur)//pcur!=NULL{if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}
//在指定位置之前插⼊数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(*pphead && pphead);assert(pos);//还要判断能不能在链表中找到pos这个地址SLTNode* newnode = SLTBuyNode(x);if (pos == *pphead){SLTPushFront(pphead, x);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}newnode->next = pos;prev->next = newnode;}
}
//在指定位置之后插⼊数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);SLTNode* next = pos->next;newnode->next = next;pos->next = newnode;}
//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);if (pos == *pphead){SLTPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}
}
//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{assert(pos&&pos->next);//pos->next也要断言,因为当cur->next为NULL时,
//说明整个链表的节点都排查完了,最后还是没有找到地址为pos的结点,证明pos传值有误。SLTNode* after = pos->next;pos->next = after->next;free(after);after = NULL;}//销毁链表
//因为链表在物理结构上是不连续存储的,销毁链表必须要一个结点一个结点去销毁
void SListDesTroy(SLTNode** pphead)
{assert(*pphead && pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;//不要忘记把phead置为NULL。
}

test.c

测试输出结果为:

可判断功能都可正常实现。
3.常见疑问解答
1.什么时候使用二级指针,什么时候使用一级指针?
以尾插举例,当链表为空时,头指针phead指向NULL,尾插相当于头插,此时要改变phead的指向,让phead指向这个新节点,此时就 需要二级指针来改变一级指针的值。(if用一级指针做形参,形参的改变不影响实参)。
看下图,帮助自己更好理解
2.有关断言
assert(pphead)----  一级指针也就是phead,当链表为空的时候,phead就是为NULL,而二级指针永远指向phead,phead的地址是永远存在的,那么pphead就一定不可能为空,所以需要断言pphead
assert(*pphead)---  保证原链表中有元素,内容不为空。
assert(pos)---  pos也需断言,不可为空
有更多问题,欢迎大家提出。
感谢观看,喜欢的可以点个赞支持一下。

相关文章:

数据结构--单链表 详解(附代码

目录&#xff1a; 1&#xff1a;链表的概念及结构 2&#xff1a;实现单链表 3&#xff1a;常见疑问 解答 &#xff08;看到最后&#xff01;&#xff01;&#xff09; 一&#xff1a;链表的概念及结构 1.1 概念&#xff1a; 链表是⼀种 物理存储结构上非连续、非顺序的 存储结…...

leetcode 1749.任意子数组和的绝对值的最大值

思路&#xff1a;dp 说到绝对值&#xff0c;大家肯定不陌生&#xff0c;但是用在dp上就会使问题变得稍微复杂一些了。 我们在最大子数组和的那道题中知道&#xff0c;在状态转移的时候&#xff0c;我们会舍弃掉为负数的连续部分&#xff0c;重新构建连续的子串。但是&#xf…...

Linux进程——进程地址空间

前言&#xff1a;在讲完环境变量后&#xff0c;相信大家对Linux有更进一步的认识&#xff0c;而Linux进程概念到这也快接近尾声了&#xff0c;现在我们了解Linux进程中的地址空间&#xff01; 本篇主要内容&#xff1a; 了解程序地址空间 理解进程地址空间 探究页表和虚拟地址空…...

基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (三)

基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 大家继续看 https://lilianweng.github.io/posts/2023-06-23-agent/的文档内容 第二部分&#xff1a;内存 记忆的类型 记忆可以定义为用于获取、存储、保留以及随后检索信息的过程。人脑中有多…...

python3如何安装bs4

在python官网找到beautifulsoup模块的下载页面&#xff0c;点击"downloap"将该模块的安装包下载到本地。 将该安装包解压&#xff0c;然后在打开cmd&#xff0c;并通过cmd进入到该安装包解压后的文件夹目录下。 在该文件目录下输入"python install setup.py&quo…...

docker容器技术篇:rancher管理平台部署kubernetes集群

rancher管理平台部署kubernetes集群 Rancher 是一个 Kubernetes 管理工具&#xff0c;让你能在任何地方和任何提供商上部署和运行集群。 Rancher 可以创建来自 Kubernetes 托管服务提供商的集群&#xff0c;创建节点并安装 Kubernetes&#xff0c;或者导入在任何地方运行的现…...

【计算机网络原理】初识网络原理和一些名词解释​​

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…...

车载电子电器架构 —— 关于bus off汇总

车载电子电器架构 —— 关于bus off汇总 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明…...

Linux函数

目录 一、脚本函数 1.1 创建函数 1.2 使用函数 二、函数返回值 2.1 默认的退出状态码 2.2 使用return命令 2.3 使用函数输出 三、在函数中使用变量 3.1 向函数传达参数 3.2 在函数中处理变量 四、数组变量和函数 4.1 向函数中传递数组 4.2 从函数中返回数组 五、函数…...

如何查看centos7中Java在哪些路径下

在 CentOS 7 上&#xff0c;你可以通过几种方式查找安装的 Java 版本及其路径。以下是一些常用的方法&#xff1a; 1. 使用 alternatives 命令 CentOS 使用 alternatives 系统来管理同一命令的多个版本。你可以使用以下命令来查看系统上所有 Java 安装的配置&#xff1a; su…...

信息安全-古典密码学简介

目录 C. D. Shannon: 一、置换密码 二、单表代替密码 ① 加法密码 ② 乘法密码 ③密钥词组代替密码 三、多表代替密码 代数密码 四、古典密码的穷举分析 1、单表代替密码分析 五、古典密码的统计分析 1、密钥词组单表代替密码的统计分析 2、英语的统计规…...

面试题 01.05. 一次编辑

字符串有三种编辑操作:插入一个英文字符、删除一个英文字符或者替换一个英文字符。 给定两个字符串&#xff0c;编写一个函数判定它们是否只需要一次(或者零次)编辑。 示例 1: 输入: first "pale" second "ple" 输出: True示例 2: 输入: first &qu…...

针对头疼的UDP攻击如何定制有效的防护措施

分布式拒绝服务攻击&#xff08;Distributed Denial of Service&#xff09;简称DDoS&#xff0c;亦称为阻断攻击或洪水攻击&#xff0c;是目前互联网最常见的一种攻击形式。DDoS攻击通常通过来自大量受感染的计算机&#xff08;即僵尸网络&#xff09;的流量&#xff0c;对目标…...

怎么制作流程图?介绍制作方法

怎么制作流程图&#xff1f;在日常生活和工作中&#xff0c;流程图已经成为我们不可或缺的工具。无论是项目规划、流程优化&#xff0c;还是学习理解复杂系统&#xff0c;流程图都能帮助我们更直观地理解和表达信息。然而&#xff0c;很多人可能并不清楚&#xff0c;其实制作流…...

棱镜七彩参编《网络安全技术 软件供应链安全要求》国家标准发布

据全国标准信息公共服务平台消息显示&#xff0c;《网络安全技术 软件供应链安全要求》&#xff08;GB/T 43698-2024&#xff09;国家标准已于2024年4月25日正式发布&#xff0c;并将于2024年11月1日正式实施。棱镜七彩作为主要编制单位之一参与该国家标准的编制&#xff0c;为…...

Keepalived实现LVS高可用

6.1 KeepalivedLVS集群介绍 Keepalived和LVS共同构建了一个高效的负载均衡和高可用性解决方案&#xff1a;LVS作为负载均衡器&#xff0c;负责在集群中的多个服务器间分配流量&#xff0c;以其高性能和可扩展性确保应用程序能够处理大量的并发请求&#xff1b;而Keepalived则作…...

【力扣】1089.复写零

原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 给你一个长度固定的整数数组 arr &#xff0c;请你将该数组中出现的每个零都复写一遍&#xff0c;并将其余的元素向右平移。 注意&#xff1a;请不…...

Golang实践录:gin框架使用自定义日志模块

本文介绍在 Golang 的 gin 框架中使用自定义日志模块的一些方法。 背景 很早之前就实现并使用了自己封装的日志模块&#xff0c;但一直没有将gin框架内部的日志和日志模块结合。gin的日志都是在终端上打印的&#xff0c;排查问题不方便。趁五一假期&#xff0c;集中研究把此事…...

Django之配置数据库

一&#xff0c;创建项目 二&#xff0c;将项目的setting.py中的 DATABASES {default: {ENGINE: django.db.backends.sqlite3,NAME: BASE_DIR / db.sqlite3,} }替换成如下&#xff08;以mysql为例&#xff09; DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: …...

Ajax 笔记02

01 jq中的ajax方法中的dataType属性 dataType属性的属性值有以下几种: xml 返回数据按照xml解析 json 返回的数据按照json代码解析 script 返回的数据按照js代码解析 text 把返回的数据按照普通文本解析 jsonp 跨域 json: javascript object notation(js对象简谱) json整体…...

SpringCloud微服务里,用Zuul网关聚合Swagger文档的完整配置流程(含踩坑记录)

SpringCloud微服务架构下Zuul网关聚合Swagger文档的实战指南 在微服务架构中&#xff0c;API文档的管理一直是个令人头疼的问题。想象一下&#xff0c;当你的系统由十几个甚至几十个微服务组成时&#xff0c;开发人员要记住每个服务的接口地址和文档路径几乎是不可能的任务。更…...

别再只装软件了!TIA Portal Openness安装后必做的用户组配置(Win10避坑指南)

别再只装软件了&#xff01;TIA Portal Openness安装后必做的用户组配置&#xff08;Win10避坑指南&#xff09; 当你兴冲冲地安装完TIA Portal和Openness组件&#xff0c;准备大展拳脚时&#xff0c;突然弹出一个"CAx操作无法启动"的错误提示——这种挫败感&#xf…...

5分钟快速上手:如何用Video2X免费AI工具让老旧视频焕发4K新生

5分钟快速上手&#xff1a;如何用Video2X免费AI工具让老旧视频焕发4K新生 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/v…...

NotebookLM深度绑定Google Drive的终极方案(含OAuth2作用域最小化清单+服务账号部署模板)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;NotebookLM深度绑定Google Drive的终极方案&#xff08;含OAuth2作用域最小化清单服务账号部署模板&#xff09; NotebookLM 本地知识增强能力依赖于安全、稳定且权限精确的 Google Drive 数据接入。直…...

从波形到Mel谱图:机器学习音频特征提取的完整实践指南

1. 音频信号处理基础&#xff1a;从物理世界到数字信号 第一次接触音频信号处理时&#xff0c;我被那一串串看似随机的波形数据弄得一头雾水。直到后来才明白&#xff0c;这些数字背后其实对应着我们熟悉的物理现象——声音。声音的本质是空气压力的变化&#xff0c;就像水面泛…...

ROS机器人开发:用tf_monitor和tf_echo快速诊断你的坐标转换问题(附真实案例)

ROS机器人坐标转换问题诊断实战&#xff1a;从工具使用到思维升级 当机器人的激光雷达数据与地图匹配出现偏移&#xff0c;或者机械臂末端执行器总是偏离目标位置几厘米时&#xff0c;有经验的开发者会第一时间检查坐标转换系统。ROS中的tf库虽然强大&#xff0c;但一旦出现问题…...

LogExpert终极指南:Windows平台最强大的免费开源日志分析工具

LogExpert终极指南&#xff1a;Windows平台最强大的免费开源日志分析工具 【免费下载链接】LogExpert Windows tail program and log file analyzer. 项目地址: https://gitcode.com/gh_mirrors/lo/LogExpert LogExpert是Windows平台上最强大的免费开源日志分析工具&…...

Windows网络测速终极指南:iperf3免费工具完整教程

Windows网络测速终极指南&#xff1a;iperf3免费工具完整教程 【免费下载链接】iperf3-win-builds iperf3 binaries for Windows. Benchmark your network limits. 项目地址: https://gitcode.com/gh_mirrors/ip/iperf3-win-builds 还在为网络速度不稳定而烦恼吗&#x…...

League-Toolkit终极指南:英雄联盟玩家的智能自动化神器

League-Toolkit终极指南&#xff1a;英雄联盟玩家的智能自动化神器 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 如果你是英雄联盟玩家&…...

Laravel 8.x核心特性深度解析

好的&#xff0c;Laravel 8.x 版本引入了多项重要改进和新特性&#xff0c;旨在提升开发效率和功能。以下是其主要特性&#xff1a;Laravel Jetstream这是一个全新的应用脚手架&#xff0c;提供了登录、注册、邮箱验证、双因素认证、会话管理、API 支持&#xff08;通过 Sanctu…...