【3-22 list 詳解STL C++ 】

先看代碼,常用的就是代碼中有的那些

#include <bits/stdc++.h>
using namespace std;
int main() {list<int> mylist;for(int i=0;i<5;i++){mylist.push_back(i);//TODO}for(const auto&i:mylist)cout<<i<<'\n';//fanzhuanreverse(mylist.begin(),mylist.end());cout<<" 	//fanzhuan\n ";for(const auto&i:mylist){cout<<i<<'\n';	//TODO}mylist.insert(++mylist.begin(),9);cout<<" 	//插入\n ";for(const auto&i:mylist){cout<<i<<'\n';	//TODO}	mylist.erase(++ mylist.begin(),--mylist.end());//刪除了一個區間的數cout<<"size"<<mylist.size()<<'\n';for(const auto&i:mylist){cout<<i<<'\n';	//TODO}	return 0;}
  1. List的核心操作:如push_back, push_front, pop_back, pop_front等。
  2. 迭代器使用:如何遍歷list,不同迭代器的區別(正向、反向)。
  3. 容量與大小管理:size(), empty(), clear()等方法,以及與vector在內存管理上的對比。
  4. 元素訪問:通過迭代器和下標訪問的效率差異,at()方法的使用。
  5. 插入與刪除操作:在特定位置插入或刪除元素的效率,erase方法的不同用法。
  6. 自定義類型支持:如何存儲對象,需要重載哪些運算符。
  7. 性能比較:list在插入刪除時的優勢,以及隨機訪問的劣勢。
  8. 實際應用案例:比如實現棧、隊列,或者作為鏈表結構的使用場景。

一、核心成員函數詳解(修正拼寫錯誤后)

函數名稱功能說明示例代碼注意事項
push_back()在鏈表尾部插入元素lst.push_back(10);時間 O(1)
push_front()在鏈表頭部插入元素lst.push_front(20);時間 O(1)
pop_back()移除鏈表尾部元素lst.pop_back();空容器調用會崩潰
pop_front()移除鏈表頭部元素lst.pop_front();同上
size()返回鏈表元素個數int n = lst.size();O(1)
empty()檢查鏈表是否為空if (lst.empty()) {...}O(1)
clear()清空所有元素lst.clear();O(n)
front()獲取第一個元素的引用int x = lst.front();空容器調用崩潰
back()獲取最后一個元素的引用int y = lst.back();同上
begin()返回首元素的迭代器auto it = lst.begin();
end()返回尾元素后繼的迭代器auto rit = lst.rbegin();
insert(pos, val)在位置 pos 前插入元素lst.insert(lst.begin()+1, 30);時間 O(n)
erase(pos)刪除位置 pos 的元素lst.erase(lst.begin()+1);同上

二、常用擴展函數(圖片未提及)

函數名稱功能說明示例代碼
emplace_back(val)在尾部直接構造元素(比 push_back 更高效)lst.emplace_back(100);
splice(pos, other)將另一個鏈表的元素插入到當前位置lst.splice(it, other_lst);
merge(other)合并兩個有序鏈表(保持有序性)auto merged = merge(&a, &b);
remove(val)刪除所有等于 val 的元素lst.remove(5);
reverse()反轉鏈表順序lst.reverse();
assign(range)用區間內的元素覆蓋當前鏈表lst.assign(arr.begin(), arr.end());

三、安全操作示例

#include <iostream>
#include <list>
using namespace std;int main() {list<int> lst;// 安全插入lst.push_back(1);lst.push_front(2);// 避免空容器操作if (!lst.empty()) {cout << "首元素: " << lst.front() << endl; // 輸出 2cout << "末元素: " << lst.back() << endl;   // 輸出 1}// 使用迭代器安全刪除if (lst.size() > 0) {auto it = lst.begin();lst.erase(it); // 刪除第一個元素}return 0;
}

四、list vs vector 對比分析

特性list(雙向鏈表)vector(動態數組)
內存分配分散的內存塊(指針開銷大)連續內存塊(緊湊存儲)
插入/刪除效率頭部 O(1),中間 O(1)(已知位置)頭部 O(n),中間 O(n)
隨機訪問O(n)(需遍歷)O(1)(直接索引)
內存占用較高(每個節點存儲指針)較低(僅存儲數據)
迭代器失效性僅被刪除元素的迭代器失效所有迭代器可能失效(擴容時)
適用場景頻繁插入/刪除元素頻繁隨機訪問元素

1. 實現LRU緩存(基于list和unordered_map)
#include <list>
#include <unordered_map>
using namespace std;template<typename K, typename V>
class LRUCache {
private:list<pair<K, V>> cache; // 按訪問順序排列unordered_map<K, typename list<pair<K, V>>::iterator> pos_map;size_t capacity;public:LRUCache(size_t cap) : capacity(cap) {}void get(K key) {auto it = pos_map.find(key);if (it == pos_map.end()) return;// 將節點移到頭部(最近使用)cache.splice(cache.begin(), cache, it->second);}void put(K key, V value) {auto it = pos_map.find(key);if (it != pos_map.end()) {// 更新值并移到頭部it->second->second = value;cache.splice(cache.begin(), cache, it->second);} else {if (cache.size() >= capacity) {// 刪除末尾元素(最久未使用)auto last = cache.end();--last;pos_map.erase(last->first);cache.pop_back();}// 插入新節點到頭部auto newNode = cache.emplace_front(key, value);pos_map[key] = newNode;}}
};
2. 雙向鏈表反轉
void reverse_list(list<int>& lst) {auto it1 = lst.begin();auto it2 = lst.end();while (it1 != it2) {swap(*it1, *it2);++it1;--it2;}
}

二、核心內容架構

1. 雙向鏈表節點的底層實現

? 節點結構體解析

template<typename T>
struct Node {T data;          // 存儲元素Node* prev;       // 前驅指針Node* next;       // 后繼指針Node(const T& val) : data(val), prev(nullptr), next(nullptr) {}
};

? 內存分配策略
? 節點池技術:預分配內存塊減少動態分配開銷
? 分配器模式:與vector不同的allocator實現(如__gnu_pbds::node_allocator)

2. 關鍵成員函數源碼剖析

? 構造函數

list() : head(nullptr), tail(nullptr), size(0) {} // 空鏈表初始化
list(initializer_list<T> il) { ... } // 包含初始化列表的構造

? 動態擴容機制
? 無需擴容:鏈表結構支持O(1)時間復雜度的頭尾插入/刪除
? 迭代器失效性:只有被刪除元素的迭代器會失效,其他迭代器保持有效

3. 高效操作實現原理

? push_back()

void push_back(const T& val) {Node* newNode = allocator.allocate(1);allocator.construct(newNode, val);if (empty()) {head = tail = newNode;} else {tail->next = newNode;newNode->prev = tail;tail = newNode;}++size;
}

? insert(pos, val)
? 定位節點:雙向鏈表支持O(n)時間復雜度定位
? 指針調整:四步操作(新節點創建→前后指針重新鏈接)

4. 與vector的對比實驗
操作listvector
頭部插入O(1)O(n)
中間插入O(1)(已知位置)O(n)
隨機訪問O(n)O(1)
內存占用較高(指針開銷)較低(緊湊存儲)
適用場景頻繁插入/刪除頻繁隨機訪問

三、代碼示例與調試

1. 實現鏈表反轉(迭代器版)
void reverse_list(list<int>& lst) {auto it1 = lst.begin();auto it2 = lst.end();while (it1 != it2) {swap(*it1, *it2);++it1;--it2;}
}
2. 模擬LRU緩存淘汰算法
#include <list>
#include <unordered_map>template<typename K, typename V>
class LRUCache {
private:list<pair<K, V>> cache; // 按訪問順序排列unordered_map<K, typename list<pair<K, V>>::iterator> pos_map;size_t capacity;public:LRUCache(size_t cap) : capacity(cap) {}void get(K key) {auto it = pos_map.find(key);if (it == pos_map.end()) return;// 將訪問的節點移到鏈表頭部cache.splice(cache.begin(), cache, it->second);}void put(K key, V value) {auto it = pos_map.find(key);if (it != pos_map.end()) {// 存在則更新值并移動到頭部it->second->second = value;cache.splice(cache.begin(), cache, it->second);} else {if (cache.size() >= capacity) {// 淘汰末尾元素auto last = cache.end();--last;pos_map.erase(last->first);cache.pop_back();}// 插入新節點到頭部auto newNode = cache.emplace_front(key, value);pos_map[key] = newNode;}}
};

四、進階知識點

1. 內存泄漏檢測技巧

? 使用Valgrind工具檢測鏈表節點泄漏:

valgrind --leak-check=yes ./a.out
2. 自定義內存池優化
template<typename T>
class FastList : public std::list<T> {
private:struct Pool {T* buffer;size_t capacity;Pool(size_t cap) : capacity(cap) {buffer = static_cast<T*>(malloc(cap * sizeof(T)));}~Pool() { free(buffer); }};Pool pool(1024); // 預分配1024個節點// 重載allocatorusing allocator_type = typename std::list<T>::allocator_type;allocator_type alloc;public:FastList() : std::list<T>(alloc), pool(1024) {this->allocator = alloc; // 綁定自定義分配器}
};

五、學習建議

  1. 配套書籍推薦
    ? 《Effective STL》Item 10:選擇合適的容器
    ? 《C++ Primer》第16章:鏈表容器詳解

  2. 實驗環境配置

    g++ -std=c++17 -Wall -Wextra list_exercise.cpp -o list_exercise
    
  3. 常見錯誤總結
    ? 誤用operator[]訪問鏈表(僅vector支持隨機訪問)
    ? 忘記釋放自定義分配的內存(內存泄漏)
    ? 在迭代器失效后繼續操作(未理解鏈表結構特性)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/74551.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74551.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/74551.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

田間機器人幼苗視覺檢測與護苗施肥裝置研究(大綱)

田間機器人幼苗視覺檢測與護苗施肥裝置研究 基于多光譜視覺與精準施肥的農業機器人系統設計 第一章 緒論 1.1 研究背景與意義 農業智能化需求&#xff1a; 傳統幼苗檢測依賴人工&#xff0c;效率低且易遺漏弱苗/病苗施肥不精準導致資源浪費和環境污染 技術挑戰&#xff1a;…

如何在Linux CentOS上安裝和配置Redis

如何在Linux CentOS上安裝和配置Redis 大家好&#xff0c;我是曾續緣。歡迎來到本教程&#xff01;今天我將向您介紹在Linux CentOS上安裝和配置Redis的詳細步驟。Redis是一個高性能的鍵值存儲系統&#xff0c;常用于緩存、消息隊列和數據持久化等應用場景。讓我們一起開始吧&…

requests庫post方法怎么傳params類型的參數

在使用 requests 庫的 post 方法時&#xff0c;params 類型的參數通常用于在 URL 中作為查詢字符串傳遞。這與 data 或 json 參數不同&#xff0c;后者是放在請求體中的。下面詳細介紹如何在使用 post 方法時傳遞 params 參數。 使用 params 參數 params 參數接受一個字典或包…

C++常見問題與思考

TLS&#xff08;線程本地存儲&#xff09;原理 線程本地存儲&#xff08;Thread Local Storage&#xff0c;TLS&#xff09;是一種機制&#xff0c;它允許每個線程擁有自己獨立的變量實例&#xff0c;這些變量的生命周期與線程相同。也就是說&#xff0c;不同線程對同一個 TLS…

如何快速下載并安裝 Postman?

從下載、安裝、啟動 Postman 這三個方面為大家詳細講解下載安裝 Postman 每一步操作&#xff0c;幫助初學者快速上手。 Postman 下載及安裝教程(2025最新)

使用Gitee Go流水線部署個人項目到服務器指南

使用Gitee Go流水線部署個人項目到服務器指南 前言&#xff01;&#xff01;&#xff01; 本文解決的問題&#xff1a; 你有一臺ECS服務器&#xff0c;你在上面部署了一個Java服務也就是一個jar&#xff0c;你覺著你每次手動本地打包&#xff0c;上傳&#xff0c;在通過命令去…

Linux第一節:Linux系統編程入門指南

摘要 本文面向Linux初學者&#xff0c;系統講解操作系統核心概念、Shell命令實戰、權限管理精髓及目錄結構解析。通過思維導圖命令示例原理解析的方法&#xff0c;幫助開發者快速構建Linux知識體系&#xff0c;掌握生產環境必備技能。 一、Linux的前世今生&#xff1a;從實驗室…

【Linux 維測專欄 5 -- linux pstore 使用介紹】

文章目錄 Linux pstore 功能簡介1. pstore 概述2. pstore 的核心功能3. pstore 的工作原理4. pstore 的使用示例5. pstore 的優勢6. 典型應用場景配置示例1)DTS配置2)config配置運行測試及log問題小結Linux pstore 功能簡介 1. pstore 概述 pstore(Persistent Storage)是…

在 ASP .NET Core 9.0 中使用 Scalar 創建漂亮的 API 文檔

示例代碼&#xff1a;https://download.csdn.net/download/hefeng_aspnet/90407900 Scalar 是一款可幫助我們為 API 創建精美文檔的工具。與感覺有些過時的默認 Swagger 文檔不同&#xff0c;Scalar 為 API 文檔提供了全新而現代的 UI。其簡潔的設計讓開發人員可以輕松找到測試…

Rabbitmq消息被消費時拋異常,進入Unacked 狀態,進而導致消費者不斷嘗試消費(下)

一、消費流程圖 消息在消費出現異常的時候&#xff0c;將一直保留在消息隊列&#xff0c;所以你會看到以下奇怪的現象&#xff1a; 消息隊列僅有5個消息&#xff0c; 投遞速度也非常快&#xff0c;結果卻一直無法消費掉。 二、重試策略 重試機制的使用場景&#xff1a;重試機制…

【STM32】知識點介紹二:GPIO引腳介紹

文章目錄 一、概述二、GPIO的工作模式三、寄存器編程 一、概述 GPIO&#xff08;英語&#xff1a;General-purpose input/output&#xff09;,即通用I/O(輸入/輸出)端口&#xff0c;是STM32可控制的引腳。STM32芯片的GPIO引腳與外部設備連接起來&#xff0c;可實現與外部通訊、…

JavaScript流程控制精講(二)運算符與循環實戰

JavaScript流程控制精講&#xff08;二&#xff09;運算符與循環實戰 學習目標&#xff1a;掌握條件判斷與循環控制&#xff0c;實現基礎業務邏輯 核心要點&#xff1a;運算符優先級 | 短路運算 | 循環優化 | 項目實戰 一、運算符進階技巧 1.1 算術運算符 console.log(5 % 3)…

如何在IPhone 16Pro上運行python文件?

在 iPhone 16 Pro 上運行 Python 文件需要借助第三方工具或遠程服務&#xff0c;以下是具體實現方法和步驟&#xff1a; 一、本地運行方案&#xff08;無需越獄&#xff09; 使用 Python 編程類 App 以下應用可在 App Store 下載&#xff0c;支持直接在 iPhone 上編寫并運行 …

【趙渝強老師】達夢數據庫的數據庫對象

達夢數據庫中包含各種數據庫對象&#xff0c;主要分為兩大類型&#xff1a;基本數據庫對象和復雜數據庫對象。下面分別進行介紹。 視頻講解如下 【趙渝強老師】達夢數據庫的數據庫對象 一、 基本數據庫對象 常見的基本數據庫對象有&#xff1a;表、索引、視圖、序列、同義詞等…

【每日算法】Day 6-1:哈希表從入門到實戰——高頻算法題(C++實現)

摘要 &#xff1a;掌握高頻數據結構&#xff01;今日深入解析哈希表的核心原理與設計實現&#xff0c;結合沖突解決策略與大廠高頻真題&#xff0c;徹底掌握O(1)時間復雜度的數據訪問技術。 一、哈希表核心思想 哈希表&#xff08;Hash Table&#xff09; 是一種基于鍵值對的…

LeetCode 第29題、30題

LeetCode 第29題&#xff1a;兩數相除 題目描述 給你兩個整數&#xff0c;被除數dividend和除數divisor。將兩數相除&#xff0c;要求不使用乘法、除法和取余運算。整數除法應該向零截斷&#xff0c;也就是截去其小數部分。例如&#xff0c;8.345將被截斷為8&#xff0c;-2.733…

26考研——樹與二叉樹_樹、森林(5)

408答疑 文章目錄 二、樹、森林樹的基本概念樹的定義和特性樹的定義樹的特性 基本術語樹的基本術語和概念祖先、子孫、雙親、孩子、兄弟和堂兄弟結點的層次、度、深度和高度樹的度和高度分支結點和葉結點有序樹和無序樹路徑和路徑長度 森林的基本術語和概念森林的定義森林與樹的…

【HarmonyOS Next之旅】DevEco Studio使用指南(六)

目錄 1 -> 在模塊中添加Ability 1.1 -> Stage模型添加UIAbility 1.1.1 -> 在模塊中添加UIAbility 1.1.2 -> 在模塊中添加Extension Ability 2 -> 創建服務卡片 2.1 -> 概述 2.2 -> 使用約束 2.3 -> 創建服務卡片 2.4 -> 創建動態/靜態卡片…

Langchain 多模態輸入和格式化輸出

多模態輸入 圖片處理&#xff08;最高頻&#xff09; 1.1 URL形式&#xff08;推薦大文件&#xff09; from langchain.schema import HumanMessage from langchain.chat_models import ChatOpenAIchat ChatOpenAI(model"gpt-4-vision-preview")message HumanMes…

Excel多級聯動下拉菜單的自動化設置(使用Python中的openpyxl模塊)

1 主要目的 在Excel中&#xff0c;經常會遇到需要制作多級聯動下拉菜單的情況&#xff0c;要求單元格內填寫的內容只能從指定的多個選項中進行選擇&#xff0c;并且需要設置多級目錄&#xff0c;其中下級目錄的選項內容要根據上級目錄的填寫內容確定&#xff0c;如下圖所示&am…