零基础小白在学习链表(LinkedList)的思考 带你拆解底层逻辑

发布时间:2026/7/15 2:58:30

零基础小白在学习链表(LinkedList)的思考 带你拆解底层逻辑
在数据结构中我们知道顺序表虽然尾插的时间复杂度O(1),但其无论是中间/头部的插⼊删除时间复杂度O(N)),还是增容时所面临空间的消耗都不可忽视思考我们当如何解决以上问题呢一、什么是链表其与数组的区别是什么1、链表一种物理上不连续但数据元素的逻辑顺序通过链表中指针次序所链接的存储结构2、其与数组的区别对比维度数组顺序表单链表无尾指针内存存储物理内存连续内存碎片化、不连续访问方式支持arr[i] 直接取O(1)不支持必须从头遍历O(n)头部插入/删除O(n)所有元素后移O(1)仅修改指针指向尾部插入均摊O(1)偶尔扩容拷贝O(n)每次要遍历到末尾中间插入/删除O(n)后续元素整体移位O(n)需要先找到目标位置空间开销仅存储数据额外开销小每个节点多存1个next指针额外内存开销大容量大小固定/动态扩容扩容有性能损耗无固定上限按需申请节点无需扩容3、链表结构(以单链表SLT [Single Linked Table]为例#includestdio.h#includestdlib.h// 1. 定义节点结构体structSLTNode{intdata;structSLTNode*next;};// 2. 给结构体起别名typedefstructSLTNodeNode;// 3. 给结构体指针起别名简化代码typedefstructSLTNode*PNode;采用struct关键字定义链表节点结构体节点分为两部分数据域 int data用于存储链表需要保存的数据可按需更换数据类型指针域 struct SListNode* next一级结构体指针存储下一个相邻节点的内存地址通过地址串联所有节点形成链式结构。使用typedef对结构体及结构体指针重命名Node等价于 struct SLTNode代表单个节点实体PNode等价于 struct SLTNode*代表节点指针简化链表操作代码书写。单链表逻辑特征节点内存不连续仅依靠next指针维系前后节点关系尾部节点next指针置NULL代表链表结束。二、链表的基本功能代码实现1、工具函数新建节点PNodeBuyNode(intx){PNode newNode(PNode)malloc(sizeof(Node));if(newNodeNULL){perror(malloc failed);exit(-1);}newNode-datax;newNode-nextNULL;returnnewNode;}malloc动态开辟内存初始化数据next 置空所有插入操作都会复用这个函数注意事项这里的newNode的类型是一级指针PNode即newNode存有对应节点的地址其指向一个节点2、打印链表遍历查看数据调试必备voidSLTPrint(PNode phead){PNode curphead-next;//跳过哨兵头节点while(cur!NULL){printf(%d - ,cur-data);curcur-next;}printf(NULL\n);}这里phead是一个不存有数据的指针(哨兵头节点)通过phead-next找到链表中第一个存有数据的有效节点通过cur指针不断将节点的数据打印而出并且将cur不断赋值成其所指向的下一节点的指针直至cur变为空指针 打印截止3、头插在链表最前面插入数据voidSLTPushFront(Node**pphead,LinkData x){Node*newnodeBuyNode(x);newnode-next*pphead;*ppheadnewnode;}错误写法// 错误写法无法修改外部头指针voidSLTPushFront(Node*phead,LinkData x){Node*newnodeBuyNode(x);newnode-nextphead;pheadnewnode;// 只修改函数内局部副本外部原指针完全不变}C 语言函数传参属于值拷贝传递如果头插函数仅使用一级指针Node* phead作形参当head为空指针时调用函数headNULL的值被拷贝到形参phead中此时phead也是NULL此时虽然他们的值都是NULL,但地址却是不一样的比如下方中的phead值为NULL 存有地址0x0003 自己地址为0x0002传入后会出现新的phead值NULL 存有地址0x0003但其地址可能时0x00A34、尾插在链表末尾插入数据(原理与3差不多) ps这里的ptail为为了找到原链表的尾节点不直接用*pphead为了便于寻找的同时不改动头节点voidSLTPushBack(Node**pphead,LinkData x){Node*newnodeBuyNode(x);Node*ptail*pphead;if(*ppheadNULL){*ppheadnewnode;}else{while(ptail-next){ptailptail-next;}ptail-nextnewnode;}}5、其余本质上实现原理与之前一致这里简要概述// 头删voidSLTPopFront(Node**pphead);// 尾删voidSLTPopBack(Node**pphead);// 按值查找节点Node*SLTFind(Node*phead,LinkData x);// 在pos节点前插入数据voidSLTInsert(Node**pphead,LinkData x,Node*pos);// 在pos节点后插入数据voidSLTInsertAfter(Node*pos,LinkData x);// 释放整条链表并置空头指针voidSLTDestroy(Node**pphead);各功能实现与简短说明5.1. 头删 SLTPopFrontvoidSLTPopFront(Node**pphead){Node*del*pphead;*ppheaddel-next;free(del);}说明可能修改头指针使用二级指针直接更新表头并释放原首节点。5.2. 尾删 SLTPopBackvoidSLTPopBack(Node**pphead){// 链表仅有一个节点if((*pphead)-nextNULL){free(*pphead);*ppheadNULL;return;}// 找到倒数第二个节点Node*cur*pphead;while(cur-next-next)curcur-next;free(cur-next);cur-nextNULL;}说明链表只剩单个节点时需要置空头指针必须二级指针。5.3. 查找 SLTFindNode*SLTFind(Node*phead,LinkData x){Node*curphead;while(cur){if(cur-datax)returncur;curcur-next;}returnNULL;}说明仅遍历读取数据不修改表头一级指针即可。5.4. 指定节点前插入 SLTInsertvoidSLTInsert(Node**pphead,LinkData x,Node*pos){Node*newnodeBuyNode(x);// 插入位置为头部更新表头if(*ppheadpos){newnode-next*pphead;*ppheadnewnode;return;}// 寻找 pos 的前驱节点Node*cur*pphead;while(cur-next!pos)curcur-next;cur-nextnewnode;newnode-nextpos;}说明若 pos 是头节点会改变链表头部使用二级指针。5.5. 指定节点后插入 SLTInsertAftervoidSLTInsertAfter(Node*pos,LinkData x){Node*newnodeBuyNode(x);newnode-nextpos-next;pos-nextnewnode;}说明永远不会改动链表头部仅修改节点内部 next一级指针够用。5.6. 销毁链表 SLTDestroyvoidSLTDestroy(Node**pphead){assert(pphead);Node*cur*pphead;while(cur){Node*nextcur-next;free(cur);curnext;}// 外部头指针置空防止野指针*ppheadNULL;}说明销毁后需要清空外部头指针变量必须二级指针。总结需要修改外部头指针头删、尾删、pos 前插、销毁链表 → 参数 Node**仅遍历 / 后置插入不改动表头查找、pos 后插 → 参数 Node*二级指针核心逻辑C 语言值传递只有传入指针变量的地址才能修改外部原始指针。

相关新闻

全景成像技术(2)—从原理到实践:深入解析拼接式全景成像的核心算法与实现

全景成像技术(2)—从原理到实践:深入解析拼接式全景成像的核心算法与实现

2026/7/15 2:58:30

1. 全景成像技术基础:从单相机到多相机方案第一次尝试用单反相机拍全景图时,我对着三脚架转了整整六圈都没拍成功——后来才发现云台螺丝没拧紧。这个尴尬经历让我深刻理解了硬件稳定性的重要性。拼接式全景成像的核心思路很简单:把不同角度拍…

DevSecOps中的安全扫描与合规检查集成

DevSecOps中的安全扫描与合规检查集成

2026/7/15 2:48:30

DevSecOps中的安全扫描与合规检查集成随着数字化转型的加速,软件开发和交付的速度不断提升,传统的安全实践已难以适应现代敏捷开发的需求。DevSecOps应运而生,它将安全实践无缝集成到DevOps流程中,实现安全左移。在这一框架下&…

围棋AI分析实战:星阵围棋让先对局精解与学习启示

围棋AI分析实战:星阵围棋让先对局精解与学习启示

2026/7/15 2:48:30

围棋AI精解名局:星阵让先友谊杯41局第五局 崔哲瀚 VS 星阵围棋 在围棋AI技术飞速发展的今天,通过AI分析经典对局已成为提升棋力的重要途径。本文将以星阵围棋与崔哲瀚九段的让先友谊赛第41局第五局为例,完整拆解AI的决策逻辑和关键变化&#…

Selenium实战:动态网页爬虫开发指南与东方财富股吧数据抓取

Selenium实战:动态网页爬虫开发指南与东方财富股吧数据抓取

2026/7/15 4:28:34

1. 项目概述:为什么用Selenium爬股吧?如果你尝试过用传统的requestsBeautifulSoup去爬取像东方财富股吧这样的论坛,大概率会碰一鼻子灰。你会发现,翻页按钮点了没反应,帖子列表刷不出来,或者登录状态死活保…

CesiumWidget初始化失败:从WebGL兼容性到CESIUM_BASE_URL配置的深度排错指南

CesiumWidget初始化失败:从WebGL兼容性到CESIUM_BASE_URL配置的深度排错指南

2026/7/15 4:28:34

1. 当CesiumWidget初始化失败时,先检查WebGL兼容性遇到"CesiumWidget初始化失败"的错误提示时,第一步要确认的是浏览器是否支持WebGL。这个错误经常会让开发者一头雾水,但实际上它可能只是浏览器环境的问题。我遇到过不少案例&…

从NIST到AMDIS:如何构建高效的GC-MS化合物鉴定工作流?

从NIST到AMDIS:如何构建高效的GC-MS化合物鉴定工作流?

2026/7/15 4:28:34

1. GC-MS化合物鉴定的核心挑战做GC-MS分析的朋友们应该都深有体会,最头疼的就是遇到复杂样品中的共流出峰。我去年分析一个环境污染物样品时,色谱图上两个峰完全重叠,用常规的NIST谱库检索根本分不清到底是哪种化合物。这种时候就需要一套系统…

协议分析:WebSocket数据抓取——从握手到帧解析的完整实战指南

协议分析:WebSocket数据抓取——从握手到帧解析的完整实战指南

2026/7/15 4:28:34

文章目录 每日一句正能量 一、引言:为什么需要抓取WebSocket数据? 二、WebSocket握手:从HTTP到全双工的协议升级 2.1 握手流程解析 2.2 Python实现握手验证 三、WebSocket帧结构:二进制层面的数据解析 3.1 帧头字段详解 3.2 掩码机制与解码 3.3 Python帧解析器实现 四、心跳…

骁龙移动平台双卡双待DSDS的技术内幕(6): DSDS模式下的IMS/VoLTE注册与通话管理

骁龙移动平台双卡双待DSDS的技术内幕(6): DSDS模式下的IMS/VoLTE注册与通话管理

2026/7/15 4:28:33

系列文章目录:本文是“骁龙移动平台双卡双待DSDS的技术内幕”系列的第六篇,聚焦双卡场景下IMS服务注册和VoLTE/VoNR通话管理的技术细节。1. IMS在DSDS中的特殊性 1.1 为什么IMS在双卡中复杂? IMS 在 DSDS 中的挑战:每张卡需要独立…

【计算机网络之TCP/UDP篇】TCP三次握手与四次挥手:从原理到实战调优

【计算机网络之TCP/UDP篇】TCP三次握手与四次挥手:从原理到实战调优

2026/7/15 4:18:33

1. TCP三次握手的底层原理TCP三次握手是建立可靠网络连接的基石。想象一下你打电话给朋友的过程:首先你拨号(SYN),朋友听到铃声接起电话说"喂"(SYN-ACK),你回一句"是我"&am…

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

2026/7/14 10:03:09

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator XUnity.AutoTranslator作为Unity游戏社区中最成熟的文本翻译解决方…

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

2026/7/13 20:43:19

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持 【免费下载链接】raspberrypi-kernel It provides openEuler kernel source for Raspberry Pi 项目地址: https://gitcode.com/openeuler/raspberrypi-kernel 前往项目官网免费下载&…

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

2026/7/15 0:26:43

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧 【免费下载链接】integration-test The repo contains test suits for system integration test 项目地址: https://gitcode.com/openeuler/integration-test 前往项目官网免费下载:…

【LINUX】驱动

【LINUX】驱动

2026/7/15 0:08:14

【LINUX驱动】【字符设备】【中断】【Platform】【网课 设备树】【GPIO】【PINCTRL】【INPUT】【IIC】【SPI】【网络驱动】【屏幕驱动】【一 设备树】【二 内核模块编译】【三 基本驱动框架】【四 Platform总线设备驱动框架】【五 驱动子系统】【六 综合】

【1982-2026】全国高精度建筑轮廓|村级精度|SHP矢量

【1982-2026】全国高精度建筑轮廓|村级精度|SHP矢量

2026/7/15 0:08:14

🔍 数据简介 本次分享1982-2026年全国村级精度建筑轮廓矢量数据,覆盖全国各省市区县,到村级别精细,为2026年最新实时采集成果,非网传仅60/77个城市的老旧数据。 数据含带高度/不带高度双版本,单体建筑边界精…

【1975-2026】全国水系水路数据|河流/水库/运河|SHP矢量

【1975-2026】全国水系水路数据|河流/水库/运河|SHP矢量

2026/7/15 0:08:14

🔍 数据简介 本次分享1975-2026年全国高精度水系水路矢量数据,覆盖全国全域,包含河流、水系、水库、运河、湿地、冰川、沟渠等全类别水文要素。 数据集包含双层矢量图层,字段分类清晰、要素齐全,支持2013-2026逐年完整…