基本介绍

在 C++ 标准库(STL)中,std::list 是一个基于双向链表实现的序列容器。它与 std::vectorstd::deque 等连续存储容器不同,提供了在序列中高效插入和删除元素的能力,尤其是在序列中间位置操作时优势明显。


1. std::list 的底层原理

std::list 是由一组双向链表节点组成,每个节点包含:

  • 元素数据本身

  • 指向前一个节点的指针(prev

  • 指向后一个节点的指针(next

整个链表通过节点指针串联起来,头节点的 prev 和尾节点的 next 通常指向特殊的哨兵节点或 nullptr

结构示意

nullptr <- [Node1] <-> [Node2] <-> [Node3] -> nullptr

链表不保证元素在内存上的连续存储,每个节点单独分配内存。


2. 主要接口和用法

#include <list>
#include <iostream>int main() {std::list<int> lst = {1, 2, 3};// 头部插入lst.push_front(0);// 尾部插入lst.push_back(4);// 插入到指定位置(通过迭代器)auto it = std::next(lst.begin(), 2);lst.insert(it, 99);// 遍历for (auto val : lst) {std::cout << val << " ";}// 输出: 0 1 99 2 3 4// 删除元素lst.remove(99);// 清空lst.clear();return 0;
}

常用接口

  • push_front / push_back / emplace_front / emplace_back:头尾插入

  • pop_front / pop_back:头尾删除

  • insert:在指定位置插入元素

  • erase:删除指定位置元素

  • remove / remove_if:删除满足条件的元素

  • splice:将另一个链表的部分或全部节点移动到当前链表中(无需复制,效率极高)

  • 双向迭代器支持,允许双向遍历


3. 性能特征与对比

操作std::liststd::vector备注
插入/删除头尾O(1)头部 O(n),尾部 O(1)
插入/删除中间O(1) (有迭代器)O(n)list不需移动元素
随机访问不支持(无 operator[]O(1)list只能顺序访问
内存占用较大(节点指针额外开销)较小,连续内存
缓存局部性影响访问效率

std::list 适合频繁中间插入/删除,且不需要随机访问的场景。


4. 典型使用场景

  • 需要频繁在序列中间插入、删除元素,且已知具体位置的迭代器(如链表实现的任务队列)

  • 实现算法时需要快速拆分、合并链表(splice 功能)

  • 保持迭代器或引用稳定,插入删除时不会使其他元素迭代器失效(与 vector 不同)


5. 高级用法与优化建议

5.1 利用 splice 高效合并链表

splicestd::list 独有且非常高效的操作。它允许将另一个链表的节点直接接入当前链表,避免拷贝和内存分配。

std::list<int> a = {1, 2, 3};
std::list<int> b = {4, 5, 6};// 将b的全部节点接入a的末尾,b变为空链表
a.splice(a.end(), b);

5.2 避免不必要的内存分配

每个节点都单独分配内存,频繁插入大量元素时可能导致性能瓶颈。可以考虑:

  • 批量插入,减少频繁的调用

  • 在性能要求极高时,考虑自定义内存池

5.3 迭代器有效性保证

std::list 插入和删除不会使其他节点的迭代器失效,适合要求迭代器长时间稳定的算法。

5.4 避免误用

  • 不要用 std::list 做需要随机访问的场景

  • 不要为了“感觉好”就盲目使用链表,很多时候 std::vector 更优


6. 其他常用成员函数

size():返回元素个数
empty():判断是否为空
assign(n, val):赋值n个val
remove(val):删除所有等于val的元素
unique():去除连续重复元素
reverse():反转链表
sort():排序

7. 示例:LRU缓存

#include <list>
#include <unordered_map>
using namespace std;class LRUCache {
public:LRUCache(int capacity) : cap(capacity) {}int get(int key) {auto it = mp.find(key);if (it == mp.end()) return -1;cache.splice(cache.begin(), cache, it->second);return it->second->second;}void put(int key, int value) {auto it = mp.find(key);if (it != mp.end()) {it->second->second = value;cache.splice(cache.begin(), cache, it->second);} else {if (cache.size() == cap) {mp.erase(cache.back().first);cache.pop_back();}cache.emplace_front(key, value);mp[key] = cache.begin();}}private:int cap;list<pair<int, int>> cache;unordered_map<int, list<pair<int, int>>::iterator> mp;
};

8. 总结

  • std::list 是双向链表实现,支持高效插入删除,迭代器稳定

  • 牺牲了内存局部性和随机访问能力,不适合频繁随机访问

  • 适合需要频繁中间操作或合并拆分链表的复杂算法

  • 使用时要结合具体需求,避免滥用导致性能下降

  • 利用高级接口如 splice 可实现高效链表操作

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

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

相关文章

大规模调用淘宝商品详情 API 的分布式请求调度实践

在电商数据分析、比价系统、选品工具等业务场景中&#xff0c;往往需要大规模调用淘宝商品详情 API 以获取商品标题、价格、销量、评价等核心数据。然而&#xff0c;面对淘宝开放平台的严格限流策略、海量商品 ID 的处理需求以及系统高可用要求&#xff0c;传统的单节点调用方式…

在 Windows 系统中解决 Git 推送时出现的 Permission denied (publickey) 错误,请按照以下详细步骤操作:

完整解决方案步骤&#xff1a; 1. 检查并生成 SSH 密钥 # 打开 Git Bash ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 全程按回车&#xff08;使用默认路径&#xff0c;不设密码&#xff09; 密钥将生成在&#xff1a;C:\Users\<用户名>\.ssh\ 目…

【入门级-算法-2、入门算法:枚举法】

枚举法&#xff08;Brute Force&#xff09;&#xff1a;是一种直接遍历所有可能情况的算法思想&#xff0c;适合解决数据范围较小的问题。它的核心是穷举所有可能性&#xff0c;并检查哪些情况符合要求。 枚举法的基本思想&#xff1a;计算机主要功能&#xff0c;或者说它的优…

Python/Node.js 调用taobao API:构建实时商品详情数据采集服务

在电商数据分析、价格监控、竞品分析等场景中&#xff0c;实时获取商品详情数据至关重要。淘宝提供了丰富的 API 接口&#xff0c;允许开发者合法合规地获取商品信息。本文将介绍如何使用 Python 和 Node.js 两种主流语言调用淘宝 API&#xff0c;构建一个实时商品详情数据采集…

【OpenCV】Mat详解

在OpenCV中&#xff0c;cv::Mat是用于存储图像、矩阵等多维数据的核心数据结构&#xff0c;替代了早期的IplImage&#xff08;需手动管理内存&#xff09;&#xff0c;其设计的核心目标是自动内存管理和高效数据操作。下面详细介绍其组成原理及使用方法。 一、cv::Mat的组成原理…

疏老师-python训练营-Day45Tensorboard使用介绍

浙大疏锦行知识点回顾&#xff1a; tensorboard的发展历史和原理tensorboard的常见操作tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 效果展示如下&#xff0c;很适合拿去组会汇报撑页数&#xff1a; 作业&#xff1a;对resnet18在cifar10上采用微调策略下&#xff0c;…

算法详细讲解:基础算法 - 离散化/区间合并

离散化 讲解 这里的离散化特指整数有序离散化。整个值域跨度很大&#xff0c;但是值非常稀疏的情况。 问题背景 我们有一个无限长的数轴&#xff0c;初始时每个位置上的值都是0。我们需要进行两种操作&#xff1a; 修改操作&#xff1a;在某个位置 x 上增加一个值 c。查询…

SpringBoot 实现在线查看内存对象拓扑图 —— 给 JVM 装上“透视眼”

0. 你将获得什么 一个可嵌入任何 Spring Boot 应用的内存对象拓扑服务&#xff1a;访问 /memviz.html 就能在浏览器看见对象图。 支持按类/包名过滤、按对象大小高亮、点击节点看详情。 线上可用&#xff1a;默认只在你点击“生成快照”时才工作&#xff1b;日常零开销。 1.…

STM32 HAL驱动MPU6050传感器

STM32 HAL驱动MPU6050传感器 项目概述 本项目实现了基于STM32 HAL库的MPU6050传感器驱动&#xff0c;可以读取加速度计和陀螺仪数据。项目使用I2C接口与MPU6050通信&#xff0c;并通过UART接口输出数据。 项目仓库地址&#xff1a;STM32_Sensor_Drives 硬件连接 MPU6050 I2…

flex-wrap子元素是否换行

flex-wrap设置子元素是否换行&#xff0c;默认情况下&#xff0c;项目都排在一条线&#xff08;又称”轴线”&#xff09;上。flex-wrap属性定义&#xff0c;flex布局中默认是不换行的。1、div的宽度是600px&#xff0c;每个span的宽度是150px&#xff0c;总共有5个&#xff0c…

RabbitMQ面试精讲 Day 21:Spring AMQP核心组件详解

【RabbitMQ面试精讲 Day 21】Spring AMQP核心组件详解 开篇 欢迎来到"RabbitMQ面试精讲"系列第21天&#xff01;今天我们将深入探讨Spring AMQP的核心组件&#xff0c;这是Java开发者集成RabbitMQ最常用的框架。掌握Spring AMQP不仅能提升开发效率&#xff0c;更是…

Flink TableAPI 按分钟统计数据量

一、环境版本环境版本Flink1.17.0Kafka2.12MySQL5.7.33二、MySQL建表脚本 create table user_log (id int auto_increment comment 主键primary key,uid int not null comment 用户id,event int not null comment 用户行为,logtime bigint null comment 日志时…

18.13 《3倍效率提升!Hugging Face datasets.map高级技巧实战指南》

3倍效率提升!Hugging Face datasets.map高级技巧实战指南 实战项目:使用 datasets.map 进行高级数据处理 在大模型训练过程中,数据预处理的质量直接决定了模型最终的表现。Hugging Face Datasets 库提供的 datasets.map 方法是处理复杂数据场景的瑞士军刀,本章将深入解析…

实体店获客新引擎:数据大集网如何破解传统门店引流难题

在商业竞争日益激烈的当下&#xff0c;实体店的生存与发展正面临前所未有的挑战。无论是街边的小型便利店&#xff0c;还是大型购物中心的连锁品牌&#xff0c;都在为"如何吸引顾客进店"而绞尽脑汁。传统广告投放效果不佳、线下流量持续萎缩、客户转化率难以提升………

LeetCode 分类刷题:2302. 统计得分小于 K 的子数组数目

题目一个数组的 分数 定义为数组之和 乘以 数组的长度。比方说&#xff0c;[1, 2, 3, 4, 5] 的分数为 (1 2 3 4 5) * 5 75 。给你一个正整数数组 nums 和一个整数 k &#xff0c;请你返回 nums 中分数 严格小于 k 的 非空整数子数组数目。子数组 是数组中的一个连续元素序…

TDengine IDMP 基本功能(1.界面布局和操作)

UI 布局和操作说明 TDengine IDMP 的用户界面&#xff08;UI&#xff09;设计旨在提供直观、易用的操作体验。下面介绍 UI 的主要区域和典型操作&#xff1a; 主要区域 IDMP 的用户界面是完全基于浏览器的。登录后的典型 UI 界面具有几个区域&#xff1a; 主菜单&#xff1a;AI…

QT(概述、基础函数、界面类、信号和槽)

一、概述1、QTQT是一个c的第三方库&#xff0c;是专门用来进行界面编程的一个库 1. QT本身实现了多种软件&#xff1a; 2. ubuntu系统中所有界面都是QT做的 3. 最新版本的QQ也是QT做的 4. 嵌入式编程中&#xff0c;几乎所有的上位机&#xff0c;都可以使用QT来做 QT本身除了实现…

【从零开始java学习|第六篇】运算符的使用与注意事项

目录 一、算术运算符 1. 基本算术运算符&#xff08;二元&#xff09; 2. 自增 / 自减运算符&#xff08;一元&#xff09; 二、类型转换&#xff08;隐式与强制&#xff09; 1. 隐式转换&#xff08;自动类型转换&#xff09; ​编辑 2. 强制转换&#xff08;显式类型转…

shellgpt

一、介绍 官网&#xff1a;https://github.com/TheR1D/shell_gpt ShellGPT&#xff08;shell_gpt&#xff09; 是一款把 GPT 系列大模型能力直接搬到终端 的开源命令行生产力工具。用日常英语或中文描述需求&#xff0c;就能帮你 生成、解释甚至自动执行 Shell 命令&#xff…

geoserver sql视图调用Postgis自定义函数问题记录

一、问题描述&#xff1a;geoserver sql视图调用Postgis自定义函数对点图层增加一条记录时&#xff0c;返回结果主键自增ID加了2&#xff0c;但表中数据只增加一条记录。 但在pgAdmin中直接写SQL调用Postgis自定义函数对点图层增加一条记录时&#xff0c;返回结果主键自增ID只加…