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

C++链表:从原理到实战

C链表详解链表是一种常见的数据结构用于存储一系列元素。与数组不同链表中的元素在内存中不是连续存储的而是通过指针链接在一起。链表由节点组成每个节点包含数据和指向下一个节点的指针。链表的基本概念链表由多个节点组成每个节点包含两部分数据域和指针域。数据域存储实际的数据指针域存储下一个节点的地址。链表的第一个节点称为头节点最后一个节点的指针域指向空nullptr。链表的优点在于动态内存分配可以高效地进行插入和删除操作。缺点是无法像数组那样通过索引直接访问元素需要从头节点开始遍历。链表的类型链表主要分为以下几种类型单链表每个节点只有一个指针指向下一个节点。双链表每个节点有两个指针分别指向前一个节点和后一个节点。循环链表尾节点的指针指向头节点形成一个环。单链表的实现以下是单链表的C实现示例#include iostream // 定义链表节点 struct Node { int data; Node* next; }; // 链表类 class LinkedList { private: Node* head; public: LinkedList() : head(nullptr) {} // 在链表末尾插入节点 void append(int value) { Node* newNode new Node{value, nullptr}; if (head nullptr) { head newNode; } else { Node* temp head; while (temp-next ! nullptr) { temp temp-next; } temp-next newNode; } } // 在链表头部插入节点 void prepend(int value) { Node* newNode new Node{value, head}; head newNode; } // 删除指定值的节点 void remove(int value) { if (head nullptr) return; if (head-data value) { Node* temp head; head head-next; delete temp; return; } Node* current head; while (current-next ! nullptr current-next-data ! value) { current current-next; } if (current-next ! nullptr) { Node* temp current-next; current-next current-next-next; delete temp; } } // 打印链表 void print() { Node* temp head; while (temp ! nullptr) { std::cout temp-data ; temp temp-next; } std::cout std::endl; } // 析构函数释放内存 ~LinkedList() { Node* current head; while (current ! nullptr) { Node* next current-next; delete current; current next; } } }; int main() { LinkedList list; list.append(1); list.append(2); list.append(3); list.prepend(0); list.print(); // 输出: 0 1 2 3 list.remove(2); list.print(); // 输出: 0 1 3 return 0; }双链表的实现双链表比单链表多了一个指向前一个节点的指针使得可以双向遍历。以下是双链表的C实现示例#include iostream // 定义双链表节点 struct DNode { int data; DNode* prev; DNode* next; }; // 双链表类 class DoublyLinkedList { private: DNode* head; public: DoublyLinkedList() : head(nullptr) {} // 在链表末尾插入节点 void append(int value) { DNode* newNode new DNode{value, nullptr, nullptr}; if (head nullptr) { head newNode; } else { DNode* temp head; while (temp-next ! nullptr) { temp temp-next; } temp-next newNode; newNode-prev temp; } } // 在链表头部插入节点 void prepend(int value) { DNode* newNode new DNode{value, nullptr, head}; if (head ! nullptr) { head-prev newNode; } head newNode; } // 删除指定值的节点 void remove(int value) { if (head nullptr) return; if (head-data value) { DNode* temp head; head head-next; if (head ! nullptr) { head-prev nullptr; } delete temp; return; } DNode* current head; while (current ! nullptr current-data ! value) { current current-next; } if (current nullptr) return; if (current-prev ! nullptr) { current-prev-next current-next; } if (current-next ! nullptr) { current-next-prev current-prev; } delete current; } // 打印链表 void print() { DNode* temp head; while (temp ! nullptr) { std::cout temp-data ; temp temp-next; } std::cout std::endl; } // 析构函数释放内存 ~DoublyLinkedList() { DNode* current head; while (current ! nullptr) { DNode* next current-next; delete current; current next; } } }; int main() { DoublyLinkedList list; list.append(1); list.append(2); list.append(3); list.prepend(0); list.print(); // 输出: 0 1 2 3 list.remove(2); list.print(); // 输出: 0 1 3 return 0; }循环链表的实现循环链表是单链表或双链表的变种尾节点的指针指向头节点形成一个环。以下是循环单链表的C实现示例#include iostream // 定义循环链表节点 struct CNode { int data; CNode* next; }; // 循环链表类 class CircularLinkedList { private: CNode* head; public: CircularLinkedList() : head(nullptr) {} // 在链表末尾插入节点 void append(int value) { CNode* newNode new CNode{value, nullptr}; if (head nullptr) { head newNode; newNode-next head; } else { CNode* temp head; while (temp-next ! head) { temp temp-next; } temp-next newNode; newNode-next head; } } // 在链表头部插入节点 void prepend(int value) { CNode* newNode new CNode{value, nullptr}; if (head nullptr) { head newNode; newNode-next head; } else { CNode* temp head; while (temp-next ! head) { temp temp-next; } newNode-next head; head newNode; temp-next head; } } // 删除指定值的节点 void remove(int value) { if (head nullptr) return; CNode* current head; CNode* prev nullptr; do { if (current-data value) { if (prev nullptr) { // 删除头节点 CNode* last head; while (last-next ! head) { last last-next; } if (head head-next) { head nullptr; } else { head head-next; last-next head; } delete current; return; } else { prev-next current-next; delete current; return; } } prev current; current current-next; } while (current ! head); } // 打印链表 void print() { if (head nullptr) return; CNode* temp head; do { std::cout temp-data ; temp temp-next; } while (temp ! head); std::cout std::endl; } // 析构函数释放内存 ~CircularLinkedList() { if (head nullptr) return; CNode* current head; CNode* next; do { next current-next; delete current; current next; } while (current ! head); } }; int main() { CircularLinkedList list; list.append(1); list.append(2); list.append(3); list.prepend(0); list.print(); // 输出: 0 1 2 3 list.remove(2); list.print(); // 输出: 0 1 3 return 0; }链表的应用场景链表在以下场景中非常有用动态内存分配链表可以根据需要动态分配内存适合内存需求不确定的情况。频繁插入和删除链表在插入和删除操作上比数组更高效。实现其他数据结构链表可以用来实现栈、队列、哈希表等数据结构。链表的常见操作链表的常见操作包括插入操作在链表的头部、尾部或中间插入节点。删除操作删除指定值的节点或指定位置的节点。查找操作查找链表中是否存在某个值。遍历操作遍历链表中的所有节点。反转操作反转链表的顺序。链表与数组的比较链表和数组各有优缺点内存分配数组需要连续的内存空间链表不需要。访问速度数组可以通过索引快速访问元素链表需要从头遍历。插入和删除链表在插入和删除操作上更高效数组需要移动元素。空间开销链表需要额外的空间存储指针。链表的优化为了提高链表的性能可以采取以下优化措施使用尾指针在单链表中维护一个尾指针可以快速在末尾插入节点。使用哨兵节点在链表头部添加一个哨兵节点可以简化插入和删除操作的逻辑。缓存友好性链表在内存中不连续可能导致缓存命中率低可以通过内存池优化。链表的扩展链表可以扩展为更复杂的数据结构例如跳表在链表的基础上添加多级索引提高查找效率。哈希链表结合哈希表和链表实现高效的查找和插入。块状链表将链表分成多个块每个块内部使用数组提高缓存命中率。链表的常见问题在使用链表时可能会遇到以下问题内存泄漏忘记释放链表节点的内存。空指针异常访问空指针或未初始化的指针。循环引用在双链表或循环链表中指针设置不当可能导致循环引用。性能问题链表在遍历和随机访问上性能较差。链表的调试技巧调试链表时可以采取以下技巧打印链表在关键操作后打印链表的内容检查是否正确。使用调试器使用调试器逐步执行代码观察指针的变化。边界条件测试测试空链表、单节点链表等边界条件。内存检查工具使用内存检查工具如Valgrind检测内存泄漏。链表的进阶话题对于想要深入学习链表的读者可以研究以下进阶话题递归操作使用递归实现链表的反转、合并等操作。多线程安全在多线程环境下如何安全地操作链表。持久化链表实现不可变的链表支持版本控制。并发链表使用锁或无锁技术实现并发安全的链表。链表的实际应用链表在实际开发中有广泛的应用例如文件系统文件系统的目录结构可以用链表表示。内存管理操作系统的内存管理中使用链表维护空闲内存块。图形处理图形处理中的多边形可以用链表表示顶点。网络协议网络协议中的数据包可以用链表组织。链表的练习题为了巩固对链表的理解可以尝试以下练习题反转链表编写一个函数反转单链表。检测循环编写一个函数检测链表中是否存在循环。合并链表编写一个函数合并两个有序链表。删除倒数第N个节点编写一个函数删除链表中倒数第N个节点。相交链表编写一个函数判断两个链表是否相交。链表的总结链表是一种灵活且强大的数据结构适用于动态内存分配和频繁插入删除的场景。通过理解链表的基本概念和实现方式可以更好地应用链表解决实际问题。掌握链表的常见操作和优化技巧能够提高代码的效率和可维护性。

相关文章:

C++链表:从原理到实战

C链表详解链表是一种常见的数据结构,用于存储一系列元素。与数组不同,链表中的元素在内存中不是连续存储的,而是通过指针链接在一起。链表由节点组成,每个节点包含数据和指向下一个节点的指针。链表的基本概念链表由多个节点组成&…...

ESP32-WROVER-E/IE模组硬件选型与外围电路设计实战

1. ESP32-WROVER-E与ESP32-WROVER-IE模组选型指南 第一次接触ESP32-WROVER系列模组时,很多人会被型号后缀搞晕。其实区分E和IE版本只需要记住一个关键点:字母"I"代表外部天线接口。ESP32-WROVER-IE模组预留了IPEX天线座,而ESP32-WR…...

Python基础:字符串的定义、拼接与转义字符使用

Python基础:字符串的定义、拼接与转义字符使用📚 本章学习目标:深入理解字符串的定义、拼接与转义字符使用的核心概念与实践方法,掌握关键技术要点,了解实际应用场景与最佳实践。本文属于《Python从入门到精通教程》Py…...

多智能体市场(Multi-Agent Marketplace):未来的应用分发新形态

多智能体市场(Multi-Agent Marketplace):未来的应用分发新形态 引言:迎接智能体经济的新纪元 在技术发展的历史长河中,我们见证了多个应用分发范式的革命性变迁:从早期的软件商店到移动应用生态,再到如今的SaaS平台。每一次变革都重新定义了软件的创建、分发和消费方式…...

用Dex-Net 2.0数据集训练自己的抓取检测模型:一个绕过数据瓶颈的实战思路

利用Dex-Net 2.0数据集突破机器人抓取研究的数据困境:轻量化实战指南 在机器人抓取研究领域,数据匮乏往往是制约个人研究者和小型团队的最大瓶颈。当大型科技公司能够投入数百万美元构建专用数据集时,独立研究者该如何在有限资源下开展前沿研…...

Boss-Key:Windows终极隐私保护工具,一键隐藏窗口的办公神器

Boss-Key:Windows终极隐私保护工具,一键隐藏窗口的办公神器 【免费下载链接】Boss-Key 老板来了?快用Boss-Key老板键一键隐藏静音当前窗口!上班摸鱼必备神器 项目地址: https://gitcode.com/gh_mirrors/bo/Boss-Key 在当今…...

LSTM实战:遗忘门、输入门与输出门解决长期依赖

LSTM实战:遗忘门、输入门与输出门解决长期依赖 本文是上篇《Word2Vec与CBOW算法实战》的续篇。上篇解决了"如何用词向量表示词语"的问题,但还有一个关键问题没解决:如何让模型理解前后词语之间的关联关系? 这就是 RNN 到…...

4月18日腾讯云「龙虾公开课」落地合肥!免费线下AI实战课,还有限定周边等你拿

合肥线下:免费AI实战课的吸引力4月18日,腾讯云开发者社区「龙虾公开课」将在合肥高新区中安创谷科技园二期H1栋国际会客厅举办。此次活动提供免费的线下AI Agent实战课,即使是零基础的参与者也能参与。课程涵盖1对1装机指导、现场实操工坊&am…...

工业物联网设备接入终极方案:Apache PLC4X统一协议访问平台

工业物联网设备接入终极方案:Apache PLC4X统一协议访问平台 【免费下载链接】plc4x PLC4X The Industrial IoT adapter 项目地址: https://gitcode.com/gh_mirrors/pl/plc4x 在智能制造和工业4.0时代,工厂车间里往往混杂着西门子、施耐德、三菱、…...

PyQt5入门实战:安装、QtDesigner设计与PyUIC转换完整指南

PyQt5 入门实战:安装、QtDesigner 设计与 PyUIC 转换完整指南环境说明:Python 3.9 PyQt5 5.15.4 PyCharm(Community/Professional 均适用)一、什么是 PyQt5? PyQt5 是 Qt5 框架的 Python 绑定,由 Riverba…...

别只盯着内核!RT-Thread v5.2.2里这些开发工具和测试框架的更新,同样能提升你的效率

别只盯着内核!RT-Thread v5.2.2里这些开发工具和测试框架的更新,同样能提升你的效率 当大多数开发者都在关注RT-Thread v5.2.2的内核优化和驱动升级时,那些隐藏在更新日志后半部分的工具链改进,正在悄然重塑嵌入式开发的效率边界。…...

Python数据科学实战:list、numpy与torch.tensor高效互转指南

1. 为什么需要掌握数据结构互转技巧 在数据科学和机器学习项目中,数据格式的混乱往往是bug的主要来源之一。我遇到过太多这样的情况:模型训练时突然报错,排查半天发现是输入数据的格式不对;或者在不同库之间传递数据时&#xff0c…...

生成式AI时代的产品创新:以AI Agent为核心功能的下一代APP设计

生成式AI时代的产品创新:以AI Agent为核心功能的下一代APP设计 1. 引入与连接 1.1 一个引人入胜的未来场景 想象一下,2025年的一个普通早晨: 你的手机闹钟响起,但这不是预设好的固定时间,而是你的"私人生活助理"AI Agent根据你的睡眠质量、当天日程和天气情…...

别再到处找下载链接了!Linux系统压力测试工具stress和stress-ng最新稳定版安装包获取指南

Linux系统压力测试工具stress与stress-ng权威获取指南 在Linux系统运维和性能调优领域,压力测试是不可或缺的环节。作为最常用的两款开源压测工具,stress和stress-ng能够模拟CPU、内存、IO等多种资源的高负载场景,帮助开发者验证系统稳定性。…...

5分钟搞定!Android Studio中文界面完整汉化终极指南

5分钟搞定!Android Studio中文界面完整汉化终极指南 【免费下载链接】AndroidStudioChineseLanguagePack AndroidStudio中文插件(官方修改版本) 项目地址: https://gitcode.com/gh_mirrors/an/AndroidStudioChineseLanguagePack 还在为Android St…...

如何在3分钟内免费获得Apex Legends终极压枪助手

如何在3分钟内免费获得Apex Legends终极压枪助手 【免费下载链接】Apex-NoRecoil-2021 Scripts to reduce recoil for Apex Legends. (auto weapon detection, support multiple resolutions) 项目地址: https://gitcode.com/gh_mirrors/ap/Apex-NoRecoil-2021 还在为Ap…...

从I2C波形到数据校验:用逻辑分析仪深度调试STM32驱动SHT30的全过程

从I2C波形到数据校验:用逻辑分析仪深度调试STM32驱动SHT30的全过程 当你的STM32代码无法正确读取SHT30温湿度数据时,示波器或逻辑分析仪捕获的I2C波形往往比串口打印的调试信息更有说服力。本文将带你走进硬件调试的真实战场,通过分析四种典型…...

从代码审计到漏洞挖掘:深度解析Gerapy项目管理模块的RCE漏洞(CVE-2021-32849)

从代码审计到漏洞挖掘:深度解析Gerapy项目管理模块的RCE漏洞(CVE-2021-32849) 在分布式爬虫管理领域,Gerapy作为整合Scrapy、Django等技术栈的解决方案,其安全性直接影响企业数据采集业务的稳定性。2021年曝光的CVE-20…...

ST MCSDK V6.2.0实战:手把手教你配置HSO-ST观测器,体验无感电机控制的‘快准稳’

ST MCSDK V6.2.0深度实战:HSO-ST观测器配置与无感控制优化指南 在电机控制领域,实现高精度、快速响应的无感控制一直是工程师们追求的目标。ST最新发布的MCSDK V6.2.0软件包中引入的HSO-ST(High Sensitivity Observer)观测器技术,为这一目标提…...

Multisim14仿真进阶:单管共射放大电路参数扫描与性能优化实战

1. 单管共射放大电路基础与Multisim14环境搭建 单管共射放大电路是模拟电路学习的经典案例,它就像电子世界的"扩音器",能把微弱的电信号放大到我们需要的强度。在Multisim14这个电子工程师的"虚拟实验室"里,我们可以安全…...

深入Linux内核:cgroup v2如何用单一层级解决容器资源管理的世纪难题?

Linux内核革命:cgroup v2如何用单一层级重塑容器资源管理 1. 从混乱到秩序:cgroup的演进之路 在云计算和容器化技术蓬勃发展的今天,Linux内核中的控制组(cgroup)技术已成为资源隔离和管理的基石。然而,cgro…...

052篇:NLP文本分类:判断邮件是投诉还是咨询

1. 前言 在RPA自动化中,经常会遇到需要理解文本内容的场景: 客户发来的邮件是投诉还是咨询? 工单描述属于哪个部门处理? 用户评价是正面还是负面? NLP(自然语言处理)可以自动分析文本,判断类别和情感。本文以百度NLP为例,讲解如何调用情感分析和自定义分类接口,并将…...

三步解除极域电子教室控制:JiYuTrainer让你重获电脑操作自由

三步解除极域电子教室控制:JiYuTrainer让你重获电脑操作自由 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 还在为课堂上被老师全屏控制电脑而束手无策吗&#xff1f…...

终极跨平台漫画阅读器:nhentai-cross完全指南,5分钟解锁全设备同步阅读体验

终极跨平台漫画阅读器:nhentai-cross完全指南,5分钟解锁全设备同步阅读体验 【免费下载链接】nhentai-cross A nhentai client 项目地址: https://gitcode.com/gh_mirrors/nh/nhentai-cross 还在为在不同设备间切换阅读漫画而烦恼吗?…...

保姆级教程:在YOLOv8中手把手集成SCAM注意力模块(附完整代码与配置文件)

零基础实战:YOLOv8集成SCAM注意力模块全流程解析 1. 环境准备与模块理解 在开始集成SCAM注意力模块之前,我们需要先搭建好开发环境并理解SCAM的工作原理。SCAM(Spatial Contextual Attention Module)是一种能够捕捉空间上下文信息…...

大理石平台的精度维护:日常保养与误差校正方法

好的,我们来详细说明大理石平台的精度维护方法,包括日常保养与误差校正两部分。大理石平台(或称花岗石平台)因其稳定性好、精度高,常作为精密测量和加工的基准平面。要维持其精度,需做好日常保养并掌握误差…...

嵌入式Linux驱动新选择:基于TinyDRM为ST7789V TFT屏幕编写现代化显示驱动

1. 为什么选择TinyDRM替代传统fbtft驱动 第一次接触ST7789V这类SPI接口的TFT屏幕时,大多数开发者都会选择fbtft驱动方案。我也不例外,当时在树莓派上折腾了好几天终于让屏幕亮起来。但随着项目深入,逐渐发现fbtft在嵌入式Linux上的局限性——…...

OFDM同步入门避坑指南:从‘符号对不上’到看懂STO估计曲线图

OFDM同步技术实战解析:从STO曲线图到MATLAB仿真避坑指南 刚接触OFDM同步的同学,一定对"符号定时偏差(STO)"这个术语感到既熟悉又陌生。教科书上定义清晰,但一到实际仿真就会遇到各种困惑:为什么F…...

剖析Powershell挖矿病毒:从WMI驻留到永恒之蓝横向移动的攻防实战

1. 初识Powershell挖矿病毒:当服务器CPU突然飙高时 那天早上刚到公司,运维同事小李就急匆匆跑过来:"张哥,咱们三台Web服务器CPU直接冲到100%了,用户投诉页面卡成PPT!"我连咖啡都没来得及喝就冲进…...

ELK Stack实战:构建高效企业日志分析平台

1. ELK Stack:企业日志管理的瑞士军刀 想象一下你管理着几十台服务器,每天产生的日志文件像雪片一样飞来。当系统出现故障时,你需要在海量日志中寻找那个关键的报错信息——这就像在干草堆里找一根针。这就是为什么越来越多的企业选择ELK St…...