深入剖析 C++ STL 中的 std::list 容器

基本介紹

在 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只加…