C++ STL 詳解 ——list 的深度解析與實踐指南

在 C++ 的標準模板庫(STL)中,list作為一種重要的序列式容器,以其獨特的雙向鏈表結構和豐富的操作功能,在許多編程場景下發揮著關鍵作用。深入理解list的特性與使用方法,能幫助開發者編寫出更高效、靈活的代碼。

一、list 的結構特點

list的底層是雙向鏈表結構,這意味著每個元素都存儲在獨立的結點中,每個結點通過指針分別指向其前一個元素和后一個元素。這種結構使得list在任意位置進行插入和刪除操作時,都能在常數時間內完成,效率極高。例如,當需要在鏈表中間插入一個新元素時,只需修改相關指針的指向,無需像數組那樣移動大量元素。同時,雙向鏈表的結構還支持前后雙向迭代,方便從兩個方向遍歷容器。

forward_list相比,list的雙向鏈表結構雖然在功能上更強大,但也帶來了一些額外的開銷。由于每個結點都需要額外的空間來存儲前后指針,對于存儲類型較小的元素,這些額外空間的占用可能會對內存使用產生較大影響。而且,與數組和向量不同,list不支持隨機訪問,不能通過下標直接訪問特定位置的元素,這在一些需要頻繁隨機訪問的場景下會帶來不便。

二、list 的使用方法

(一)定義方式

list提供了多種靈活的定義方式。可以構造一個空容器,如list<int> lt1;,用于后續動態添加元素。也能創建一個包含指定數量且值相同的元素的容器,像list<int> lt2(10, 2);,這里的lt2就包含了 10 個值為 2 的元素。通過拷貝構造,能復制已有容器的內容,list<int> lt3(lt2);lt2的內容復制到lt3中。此外,還可以利用迭代器或數組區間來初始化list,例如:

#include <iostream>
#include <list>
#include <string>
using namespace std;int main() {list<int> lt1;list<int> lt2(10, 2);list<int> lt3(lt2);string s("hello world");list<char> lt4(s.begin(), s.end()); int arr[] = { 1, 2, 3, 4, 5 };int sz = sizeof(arr) / sizeof(int);list<int> lt5(arr, arr + sz); // 打印各個list的內容cout << "lt1: ";for (int i : lt1) {cout << i << " ";}cout << endl;cout << "lt2: ";for (int i : lt2) {cout << i << " ";}cout << endl;cout << "lt3: ";for (int i : lt3) {cout << i << " ";}cout << endl;cout << "lt4: ";for (char c : lt4) {cout << c << " ";}cout << endl;cout << "lt5: ";for (int i : lt5) {cout << i << " ";}cout << endl;return 0;
}

?

(二)插入和刪除操作

  1. 頭部操作push_frontpop_front函數分別用于在容器頭部插入和刪除元素。這在需要頻繁在頭部添加或刪除數據的場景下非常實用,比如實現一個棧結構時,就可以利用list的這些操作。
#include <iostream>
#include <list>
using namespace std;int main() {list<int> lt;lt.push_front(1);lt.push_front(2);cout << "After push_front, list: ";for (int i : lt) {cout << i << " ";}cout << endl;lt.pop_front();cout << "After pop_front, list: ";for (int i : lt) {cout << i << " ";}cout << endl;return 0;
}

  1. 尾部操作push_backpop_back函數則用于在容器尾部進行插入和刪除操作,在實現隊列結構時經常會用到。
#include <iostream>
#include <list>
using namespace std;int main() {list<int> lt;lt.push_back(1);lt.push_back(2);cout << "After push_back, list: ";for (int i : lt) {cout << i << " ";}cout << endl;lt.pop_back();cout << "After pop_back, list: ";for (int i : lt) {cout << i << " ";}cout << endl;return 0;
}

  1. 指定位置操作insert函數支持在指定迭代器位置進行多種插入操作,包括插入一個數、插入多個相同值的數以及插入一段迭代器區間。erase函數可以刪除指定迭代器位置的元素或指定迭代器區間內的所有元素。在使用這些函數時,通常會結合<algorithm>頭文件中的find函數來定位要操作的位置。
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;int main() {list<int> lt = { 1, 2, 3, 4, 5 };auto it = find(lt.begin(), lt.end(), 3);if (it != lt.end()) {lt.insert(it, 10);  // 在找到的元素3前插入10cout << "After insert, list: ";for (int i : lt) {cout << i << " ";}cout << endl;lt.erase(it);  // 刪除元素3cout << "After erase, list: ";for (int i : lt) {cout << i << " ";}cout << endl;}return 0;
}

?

(三)迭代器使用

list的迭代器分為正向迭代器和反向迭代器。通過begin函數獲取容器中第一個元素的正向迭代器,end函數獲取最后一個元素后一個位置的正向迭代器,利用正向迭代器可以從前往后遍歷容器。而rbeginrend函數分別返回容器中最后一個元素的反向迭代器和第一個元素前一個位置的反向迭代器,方便從后往前遍歷容器。

#include <iostream>
#include <list>
using namespace std;int main() {list<int> lt = { 1, 2, 3, 4, 5 };// 正向迭代器遍歷cout << "Forward iteration: ";for (auto it = lt.begin(); it != lt.end(); ++it) {cout << *it << " ";}cout << endl;// 反向迭代器遍歷cout << "Reverse iteration: ";for (auto it = lt.rbegin(); it != lt.rend(); ++it) {cout << *it << " ";}cout << endl;return 0;
}

?

(四)元素獲取與大小控制

使用frontback函數可以輕松獲取list容器中的第一個和最后一個元素。size函數用于獲取容器中當前元素的個數,resize函數能夠調整容器的大小,根據傳入參數的不同,實現擴大或縮小容器。empty函數用于判斷容器是否為空,clear函數則可以清空容器中的所有元素。


#include <iostream>
#include <list>
using namespace std;int main() {list<int> lt = { 1, 2, 3, 4, 5 };cout << "前元素: " << lt.front() << endl;cout << "返回元素: " << lt.back() << endl;cout << "列表大小: " << lt.size() << endl;lt.resize(3);  // 縮小容器大小為3cout << "調整大小后,列表的大小: " << lt.size() << endl;if (lt.empty()) {cout << "列表為空" << endl;}else {cout << "列表不是空的" << endl;}lt.clear();if (lt.empty()) {cout << "清除后,列表為空" << endl;}else {cout << "清除后,列表不為空" << endl;}return 0;
}

?

(五)其他操作函數

  1. 排序與拼接sort函數可以將容器中的數據默認排為升序,在對數據順序有要求時十分便捷。splice函數用于兩個list容器之間的拼接,有多種拼接方式,可以將整個容器、某個元素或指定區間的數據拼接到另一個容器的指定位置,但要注意被拼接的數據會從原容器中移除。
#include <iostream>
#include <list>
using namespace std;int main() {list<int> lt1 = { 3, 1, 2 };list<int> lt2 = { 6, 4, 5 };lt1.sort();cout << "After sorting lt1: ";for (int i : lt1) {cout << i << " ";}cout << endl;lt1.splice(lt1.end(), lt2);  // 將lt2拼接到lt1的末尾cout << "After splice, lt1: ";for (int i : lt1) {cout << i << " ";}cout << endl;return 0;
}

  1. 元素刪除與去重remove函數用于刪除容器中特定值的元素,remove_if函數則可以刪除滿足特定條件的元素,unique函數用于刪除容器中連續的重復元素,不過在使用unique函數去重前,通常需要先對容器內元素進行排序。
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;bool isEven(int num) {return num % 2 == 0;
}int main() {list<int> lt = { 1, 2, 2, 3, 4, 4, 5 };lt.remove(2);  // 刪除值為2的元素cout << "After remove 2, list: ";for (int i : lt) {cout << i << " ";}cout << endl;lt.remove_if(isEven);  // 刪除偶數元素cout << "After remove_if, list: ";for (int i : lt) {cout << i << " ";}cout << endl;lt = { 1, 2, 2, 3, 3, 3 };lt.sort();lt.unique();  // 去重cout << "After unique, list: ";for (int i : lt) {cout << i << " ";}cout << endl;return 0;
}

  1. 合并與其他操作merge函數用于將一個有序list容器合并到另一個有序list容器中,合并后容器依然保持有序。reverse函數用于逆置容器中元素的位置,assign函數可以用新內容替換容器的當前內容,swap函數用于交換兩個容器的內容。
#include <iostream>
#include <list>
using namespace std;int main() {list<int> lt1 = { 1, 3, 5 };list<int> lt2 = { 2, 4, 6 };lt1.merge(lt2);  // 合并lt2到lt1cout << "After merge, lt1: ";for (int i : lt1) {cout << i << " ";}cout << endl;lt1.reverse();  // 逆置lt1cout << "After reverse, lt1: ";for (int i : lt1) {cout << i << " ";}cout << endl;list<int> lt3 = { 7, 8, 9 };lt1.assign(lt3.begin(), lt3.end());  // 用lt3的內容替換lt1cout << "After assign, lt1: ";for (int i : lt1) {cout << i << " ";}cout << endl;list<int> lt4 = { 10, 11, 12 };lt1.swap(lt4);  // 交換lt1和lt4的內容cout << "After swap, lt1: ";for (int i : lt1) {cout << i << " ";}cout << endl;return 0;
}

?

三、應用場景

  1. 數據頻繁插入和刪除:在實現一些需要頻繁進行插入和刪除操作的數據結構時,如優先隊列、緩存管理等,list的高效插入和刪除特性使其成為理想選擇。例如,在緩存管理中,當有新數據進入緩存或舊數據被淘汰時,list能夠快速調整數據順序。
#include <iostream>
#include <list>
using namespace std;class Cache {
private:list<int> cacheList;int capacity;public:Cache(int cap) : capacity(cap) {}void access(int data) {for (auto it = cacheList.begin(); it != cacheList.end(); ++it) {if (*it == data) {cacheList.erase(it);cacheList.push_front(data);return;}}if (cacheList.size() >= capacity) {cacheList.pop_back();}cacheList.push_front(data);}void printCache() {for (int i : cacheList) {cout << i << " ";}cout << endl;}
};int main() {Cache cache(3);cache.access(1);cache.access(2);cache.access(3);cache.printCache();cache.access(2);cache.printCache();cache.access(4);cache.printCache();return 0;
}

  1. 鏈表相關算法實現:由于list本身就是基于雙向鏈表結構,在實現鏈表相關的算法,如鏈表的反轉、合并等時,直接使用list容器可以簡化代碼編寫,并且能充分利用其內置的操作函數。
#include <iostream>
#include <list>
using namespace std;int main() {list<int> list1 = { 1, 2, 3 };list<int> list2 = { 4, 5, 6 };// 合并兩個listlist1.merge(list2);cout << "After merging, list1: ";for (int i : list1) {cout << i << " ";}cout << endl;// 反轉list1list1.reverse();cout << "After reversing, list1: ";for (int i : list1) {cout << i << " ";}cout << endl;return 0;
}

?

  1. 內存管理優化:在一些對內存使用有嚴格要求的場景下,如果數據元素之間的順序關系較為靈活,且不需要頻繁隨機訪問,list的動態內存分配和釋放特性可以有效避免內存碎片問題,提高內存利用率。

list作為 C++ STL 中的重要容器,以其獨特的雙向鏈表結構和豐富的操作函數,在眾多編程場景中都有著不可替代的作用。開發者在實際編程中,應根據具體需求,合理選擇使用list,充分發揮其優勢,提升程序的性能和質量。

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

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

相關文章

GenerationMixin概述

類 類名簡單說明GenerateDecoderOnlyOutput繼承自 ModelOutput&#xff0c;適用于非束搜索方法的解碼器-only模型輸出類。GenerateEncoderDecoderOutput繼承自 ModelOutput&#xff0c;適用于非束搜索方法的編碼器-解碼器模型輸出類。GenerateBeamDecoderOnlyOutput繼承自 Mod…

【備賽】藍橋杯嵌入式實現led閃爍

原理 由于藍橋杯的板子帶有鎖存器&#xff0c;并且與lcd屏幕有沖突&#xff0c;所以這個就成了考點。 主要就是用定時器來實現&#xff0c;同時也要兼顧lcd的沖突。 一、處理LCD函數 首先來解決與lcd屏幕沖突的問題&#xff0c;把我們所有用到的lcd函數改裝一下。 以下是基…

C++ 并發性能優化實戰:提升多線程應用的效率與穩定性

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家、CSDN平臺優質創作者&#xff0c;獲得2024年博客之星榮譽證書&#xff0c;高級開發工程師&#xff0c;數學專業&#xff0c;擁有高級工程師證書&#xff1b;擅長C/C、C#等開發語言&#xff0c;熟悉Java常用開發技術&#xff0c…

Python----計算機視覺處理(Opencv:道路檢測之車道線擬合)

完整版&#xff1a; Python----計算機視覺處理&#xff08;Opencv:道路檢測完整版&#xff1a;透視變換&#xff0c;提取車道線&#xff0c;車道線擬合&#xff0c;車道線顯示&#xff09; 一、獲取左右車道線的原始位置 導入模塊 import cv2 import numpy as np from matplot…

優選算法的妙思之流:分治——歸并專題

專欄&#xff1a;算法的魔法世界 個人主頁&#xff1a;手握風云 目錄 一、歸并排序 二、例題講解 2.1. 排序數組 2.2. 交易逆序對的總數 2.3. 計算右側小于當前元素的個數 2.4. 翻轉對 一、歸并排序 歸并排序也是采用了分治的思想&#xff0c;將數組劃分為多個長度為1的子…

C語言查漏補缺:基礎篇

1.原理 C語言是一門編譯型計算機語言&#xff0c;要編寫C代碼&#xff0c;C源代碼文本文件本身無法直接執行&#xff0c;必須通過編譯器翻譯和鏈接器的鏈接&#xff0c;生成二進制的可執行文件&#xff0c;然后才能執行。這里的二進制的可執行文件就是我們最終要形成的可執行程…

TPS入門DAY02 服務器篇

1.創建空白插件 2.導入在線子系統以及在線steam子系統庫 MultiplayerSessions.uplugin MultiplayerSessions.Build.cs 3.創建游戲實例以及初始化會話創建流程 創建會話需要的函數&#xff0c;委托&#xff0c;委托綁定的回調&#xff0c;在線子系統接口綁定某一個委托的控制其…

產品經理課程

原型工具 一、土耳其機器人 這個說法來源于 1770 年出現的一個騙局&#xff0c;一個叫沃爾夫岡馮肯佩倫&#xff08;Wolfgang von Kempelen&#xff09;的人為了取悅奧地利女皇瑪麗婭特蕾莎&#xff08;Maria Theresia&#xff09;&#xff0c;“制造”了一個會下國際象棋的機…

nginx中的limit_req 和 limit_conn

在 Nginx 中&#xff0c;limit_req 和 limit_conn 是兩個用于限制客戶端請求的指令&#xff0c;它們分別用于限制請求速率和并發連接數。 limit_req limit_req 用于限制請求速率&#xff0c;防止客戶端發送過多請求影響服務器性能。它通過 limit_req_zone 指令定義一個共享內存…

基于winform的串口調試助手

目錄 一、串口助手界面設計 1.1 串口配置 1.2 接收配置 1.3 發送配置 1.4 接收窗口和發送窗口 1.5 狀態顯示窗口 1.6 串口通訊控件 二、程序編寫 2.1 端口號自動識別并顯示在端口號下拉框 功能說明&#xff1a; 2.2 波特率下拉框顯示 2.3 數據位下拉框顯示 2.4 校…

Docker基礎2

如需轉載&#xff0c;標記出處 本次我們將下載一個 Docker 鏡像&#xff0c;從鏡像中啟動容器 上一章&#xff0c;安裝 Docker 時&#xff0c;獲得兩個主要組件&#xff1a; Docker 客戶端 Docker 守護進程&#xff08;有時稱為“服務器”或“引擎”&#xff09; 守護進程實…

Rocketmq2

一、生產者端防丟失 1. 發送方式選擇 同步發送&#xff1a;使用 send() 方法&#xff0c;等待 Broker 確認響應&#xff08;SendResult&#xff09;&#xff0c;確保消息已成功發送。異步發送&#xff1a;使用 sendAsync() 方法并設置回調函數&#xff0c;處理發送成功 / 失敗…

RabbitMQ詳解,RabbitMQ是什么?架構是怎樣的?

目錄 一,RabbitMQ是什么? 二,RabbitMQ架構 2.1 首先我們來看下RabbitMQ里面的心概念Queue是什么? 2.2 交換器Exchange 2.3 RabbitMQ是什么? 2.4 重點看下優先級隊列是什么? 三,RabbitMQ集群 3.1 普通集群模式 3.2 鏡像隊列集群 一,RabbitMQ是什么? 假設我們程序…

【一步步開發AI運動APP】六、運動計時計數能調用

之前我們為您分享了【一步步開發AI運動小程序】開發系列博文&#xff0c;通過該系列博文&#xff0c;很多開發者開發出了很多精美的AI健身、線上運動賽事、AI學生體測、美體、康復鍛煉等應用場景的AI運動小程序&#xff1b;為了幫助開發者繼續深耕AI運動領域市場&#xff0c;今…

MySQL——DQL的多表查詢

一、交叉連接 標準語法&#xff1a;select * from 表1 cross join 表2 where 表1.公共列 表2.公共列; 簡單語法&#xff1a;select * from 表1 , 表2 where 表1.公共列 表2.公共列; 公共列&#xff1a;兩張表具有相同含義的列&#xff0c;不是列名一樣。 …

【Linux內核】如何更加優雅閱讀Linux內核源碼(vscode)

1. 前言 因為已經習慣在Ubuntu下進行嵌入式工作開發&#xff0c;但Linux源碼在Source Insight下進行閱讀&#xff0c;一直很苦惱Linux/Windows來回切換的開發方式&#xff0c;當前發現可以通過 vscode clangd(擴展組件) 方式進行更好的內核源碼閱讀。 2. 環境 操作系統&…

21.OpenCV獲取圖像輪廓信息

OpenCV獲取圖像輪廓信息 在計算機視覺領域&#xff0c;識別和分析圖像中的對象形狀是一項基本任務。OpenCV 庫提供了一個強大的工具——輪廓檢測&#xff08;Contour Detection&#xff09;&#xff0c;它能夠幫助我們精確地定位對象的邊界。這篇博文將帶你入門 OpenCV 的輪廓…

LETTERS(DFS)

【題目描述】 給出一個rowcolrowcol的大寫字母矩陣&#xff0c;一開始的位置為左上角&#xff0c;你可以向上下左右四個方向移動&#xff0c;并且不能移向曾經經過的字母。問最多可以經過幾個字母。 【輸入】 第一行&#xff0c;輸入字母矩陣行數RR和列數SS&#xff0c;1≤R,S≤…

Day2-2:前端項目uniapp壁紙實戰

再在wallpaper新建一個目錄components 在components下新建組件common-title 記得點擊創建同名目錄 在index加 <view class"select"><common-title></common-title></view> 圖片換了下&#xff0c;原來的有點丑&#xff0c;圖片可按自己喜歡…

其他 vector 操作詳解(四十)

介紹 除去向 vector 添加元素&#xff08;如 push_back&#xff09;之外&#xff0c;vector 還提供了許多其他操作&#xff0c;這些操作大多與 string 的操作類似。通過掌握這些操作&#xff0c;我們可以方便地查詢、修改和比較 vector 中的元素&#xff0c;從而構建靈活、高效…