【C++初階】第十一站:list的介紹及使用

目錄

list的介紹及使用

1.list的含義

2.list的介紹

3.list的使用

1.list的構造

2.list iterator的使用

3.list capacity

4.list element access

5 list modifiers

尾插尾刪 和 頭插頭刪

insert 和 erase

resize swap clear

6.list sort and reverse

7.list copy vector copy list

8.splice

9?list的迭代器失效


前言:

🎯個人博客:Dream_Chaser

🎈博客專欄:C++

📚本篇內容:list的介紹及使用

list的介紹及使用

1.list的含義

????????列表是序列容器,允許在序列內的任何位置進行常量時間的插入和刪除操作,以及兩個方向的迭代。

容器的分類:

2.list的介紹

1.list是可以在常數范圍內在任意位置進行插入和刪除的序列式容器,并且該容器可以前后雙向迭代。

2. list的底層是雙向鏈表結構,雙向鏈表中每個元素存儲在互不相關的獨立節點中,在節點中通過指針指向其前一個元素和后一個元素。

3. list與forward_list非常相似:最主要的不同在于forward_list是單鏈表,只能朝前迭代,已讓其更簡單高效。

4. 與其他的序列式容器相比(array,vector,deque),list通常在任意位置進行插入、移除元素的執行效率更好。

5. 與其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的隨機訪問,比如:要訪問list的第6個元素,必須從已知的位置(比如頭部或者尾部)迭代到該位置,在這段位置上迭代需要線性的時間開銷;list還需要一些額外的空間,以保存每個節點的相關聯信息(對于存儲類型較小元素的大list來說這可能是一個重要的因素)

3.list的使用

list中的接口比較多,此處類似,只需要掌握如何正確的使用,然后再去深入研究背后的原理,已達到可擴展的能力。以下為list中一些常見的重要接口

1.list的構造

構造函數( (constructor))
接口說明
list (size_type n, const value_type& val = value_type())
構造的 list 中包含 n 個值為 val 的元素
list()
構造空的 list
list (const list& x)
拷貝構造函數
list (InputIterator first, InputIterator last)
[first, last) 區間中的元素構造 list

void TestList1()
{list<int> l1;                         // 構造空的l1list<int> l2(4, 100);                 // l2中放4個值為100的元素list<int> l3(l2.begin(), l2.end());  // 用l2的[begin(), end())左閉右開的區間構造l3list<int> l4(l3);                    // 用l3拷貝構造l4// 以數組為迭代器區間構造l5int array[] = { 16,2,77,29 };list<int> l5(array, array + sizeof(array) / sizeof(int));// 列表格式初始化C++11list<int> l6{ 1,2,3,4,5 };// 用迭代器方式打印l5中的元素list<int>::iterator it = l5.begin();while (it != l5.end()){cout << *it << " ";++it;}cout << endl;// C++11范圍for的方式遍歷for (auto& e : l5)cout << e << " ";cout << endl;
}

2.list iterator的使用

此處,大家可暫時將迭代器理解成一個指針,該指針指向list中的某個節點

函數聲明
接口說明
begin +
end
返回第一個元素的迭代器 + 返回最后一個元素下一個位置的迭代器
rbegin +
rend
返回第一個元素的 reverse_iterator, end 位置 返回最后一個元素下一個位置的
reverse_iterator, begin 位置

【注意】

1. begin與end為正向迭代器,對迭代器執行++操作,迭代器向后移動

2. rbegin(end)與rend(begin)為反向迭代器,對迭代器執行++操作,迭代器向前移動

void TestList2()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array + sizeof(array) / sizeof(array[0]));// 使用正向迭代器正向list中的元素// list<int>::iterator it = l.begin();   // C++98中語法auto it = l.begin();                     // C++11之后推薦寫法while (it != l.end()){cout << *it << " ";++it;}cout << endl;// 使用反向迭代器逆向打印list中的元素// list<int>::reverse_iterator rit = l.rbegin();auto rit = l.rbegin();while (rit != l.rend()){cout << *rit << " ";++rit;}cout << endl;
}

3.list capacity

#include <iostream>
#include <list>int main() {// 創建一個std::list并添加幾個元素std::list<int> numbers = { 1, 2, 3, 4, 5 };// 使用size()方法打印列表中的元素數量std::cout << "The list contains " << numbers.size() << " elements." << std::endl;// 使用empty()方法檢查列表是否為空,并打印結果if (numbers.empty()) {std::cout << "The list is empty." << std::endl;}else {std::cout << "The list is not empty." << std::endl;}// 移除所有元素后,再次使用empty()檢查numbers.clear();if (numbers.empty()) {std::cout << "After clearing, the list is now empty." << std::endl;}return 0;
}

4.list element access

函數聲明
接口說明
front
返回 list 的第一個節點中值的引用
back
返回 list 的最后一個節點中值的引用

5 list modifiers

函數聲明
接口說明
push_front
list 首元素前插入值為 val 的元素
pop_front
刪除 list 中第一個元素
push_back
list 尾部插入值為 val 的元素
pop_back
刪除 list 中最后一個元素
insert
list position 位置中插入值為 val 的元素
erase
刪除 list position 位置的元素
swap
交換兩個 list 中的元素
clear
清空 list 中的有效元素
尾插尾刪 和 頭插頭刪

/ list迭代器的使用
// 注意:遍歷鏈表只能用迭代器和范圍for
void PrintList(const list<int>& l)
{// 注意這里調用的是list的 begin() const,返回list的const_iterator對象for (list<int>::const_iterator it = l.begin(); it != l.end(); ++it){cout << *it << " ";// *it = 10; 編譯不通過}cout << endl;
}//list插入和刪除
// push_back/pop_back/push_front/pop_front
void TestList3()
{int array[] = { 1, 2, 3 };list<int> L(array, array + sizeof(array) / sizeof(array[0]));// 在list的尾部插入4,頭部插入0L.push_back(4);L.push_front(0);PrintList(L);// 刪除list尾部節點和頭部節點L.pop_back();L.pop_front();PrintList(L);
}

insert 和 erase

// insert /erase 
void TestList4()
{int array1[] = { 1, 2, 3 };list<int> L(array1, array1 + sizeof(array1) / sizeof(array1[0]));// 獲取鏈表中第二個節點auto pos = ++L.begin();cout << *pos << endl;// 在pos前插入值為4的元素L.insert(pos, 4);PrintList(L);// 在pos前插入5個值為5的元素L.insert(pos, 5, 5);PrintList(L);// 在pos前插入[v.begin(), v.end)區間中的元素vector<int> v{ 7, 8, 9 };L.insert(pos, v.begin(), v.end());PrintList(L);// 刪除pos位置上的元素L.erase(pos);PrintList(L);// 刪除list中[begin, end)區間中的元素,即刪除list中的所有元素L.erase(L.begin(), L.end());PrintList(L);
}

resize swap clear

void TestList5()
{// 用數組來構造listint array1[] = { 1, 2, 3 };list<int> l1(array1, array1 + sizeof(array1) / sizeof(array1[0]));PrintList(l1);// 交換l1和l2中的元素list<int> l2;l1.swap(l2);PrintList(l1);PrintList(l2);// 將l2中的元素清空l2.clear();cout << l2.size() << endl;
}

6.list sort and reverse

void test_list2()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5); for (auto e : lt){cout << e << " ";}cout << endl;lt.reverse();for (auto e : lt){cout << e << " ";}cout << endl;//sort(lt.begin(), lt.end());//為什么這個不能用呢?那是因為,list是雙向迭代器//而標準庫里面的sort支持隨機迭代器,要用list自己的sort函數 lt.sort//升序 < lesslt.sort();//降序 > greater();//greater<int> gt;//lt.sort(gt);//匿名對象的排序,降序lt.sort(greater<int>());for (auto e : lt){cout << e << " ";}cout << endl;
}

7.list copy vector copy list

? ? ?代碼測這種性能要把它換成 Release,debug的優化沒有全開的,導致遞歸和循環,次數比較多,差異是比較大的,但是Release的差距不大。

void test_op()
{ // 初始化隨機數生成器,使用當前時間作為種子srand(time(0));// 定義常量N,表示要生成的隨機數個數const int N = 1000000;//創建兩個空的list容器list<int> lt1;list<int> lt2;// 循環N次,生成隨機數并將其添加到兩個list中for (int i = 0; i < N; i++){auto e = rand(); // 生成一個隨機數lt1.push_back(e); // 將隨機數添加到lt1的末尾lt2.push_back(e); // 將相同的隨機數添加到lt2的末尾}// 記錄開始時間,單位為clock ticks(時鐘滴答)int begin1 = clock();//返回程序所消耗的處理器時間。// 創建一個vector,使用lt2的begin和end迭代器初始化,復制lt2的內容vector<int> v(lt2.begin(), lt2.end());// 對vector v 進行排序,使用的是全局的std::sort函數,vector支持隨機訪問迭代器sort(v.begin(),v.end());// 將排序后的vector v的內容重新賦值給lt2,替換lt2當前的內容。lt2.assign(v.begin(),v.end());int end1 = clock(); // 記錄結束時間int begin2 = clock(); // 記錄另一個操作的開始時間lt1.sort(); // 直接對lt1進行排序,使用list容器自帶的sort成員函數int end2 = clock(); // 記錄結束時間// 輸出兩次排序操作所花費的時間(單位為clock ticks)printf("list copy vector sort copy list sort:%d\n",end1 - begin1);printf("list sort:%d\n",end2 - begin2);
}

8.unique and remove

void test_list4()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(3);lt.push_back(3);lt.push_back(3);lt.push_back(5);lt.push_back(5);lt.push_back(3);for (auto e : lt){cout << e << " ";}cout << endl;lt.sort();lt.unique();//去掉重復的for (auto e : lt){cout << e << " ";}cout << endl;//lt.remove(30);//刪除不存在的,不會報錯lt.remove(3);for (auto e : lt){cout << e << " ";}cout << endl;
}

8.splice

將元素從x轉移到容器中,并將它們插入位置。

void test_list5()
{list<int> mylist1, mylist2;list<int>::iterator it;for (int i = 1; i <= 4; ++i){mylist1.push_back(i);//mylist1: 1 2 3 4}for (int i = 1; i <= 3; i++){mylist2.push_back(i*10);//mylist2:10 20 30}it = mylist1.begin();++it;   //指向mylist1里面的2元素for (auto e : mylist1){cout << e << " ";}cout << endl;for (auto e : mylist2){cout << e << " ";}cout << endl;//mylist1.splice(it,mylist2);//mylist1:1 10 20 30 2 3 4//mylist2(empty)//"it" still points to 2 (the 5th element)//mylist1.splice(it, mylist2, ++mylist2.begin());//mylist:1 20 2 3 4//mylist1: 1 20 30 2 3 4mylist1.splice(it, mylist2, ++mylist2.begin(), mylist2.end());//mylist1:1 20 30 2 3 4 for (auto e : mylist1){cout << e << " ";}cout << endl;for (auto e : mylist2){cout << e << " ";}cout << endl;
}

9?list的迭代器失效

? ? ?前面說過,此處大家可將迭代器暫時理解成類似于指針,迭代器失效即迭代器所指向的節點的無效,即該節點被刪除了。因為list的底層結構為帶頭結點的雙向循環鏈表,因此在list中進行插入時是不會導致list的迭代器失效的只有在刪除時才會失效并且失效的只是指向被刪除節點的迭代器,其他迭代器不會受到影響

pos這個位置使用完畢就失效了:?

改正:

void TestListIterator()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array + sizeof(array) / sizeof(array[0]));auto it = l.begin();while (it != l.end()){l.erase(it++); // it = l.erase(it);}
}

🔧本文修改次數:0

🧭更新時間:2024年 5?月 14?日?

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

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

相關文章

Java身份證識別接口集成開發示例,身份證查詢接口

人類是有情感的&#xff0c;人們所接觸到的各種事物和信息都會被身體相應器官所接收&#xff0c;然后通過神經元傳入大腦繼而被識別&#xff0c;然后大腦便會產生對該事物的認知和情緒。人們大多喜歡熱情、有趣的事物&#xff0c;對冷冰冰、枯燥、無趣的APP基本是提不起興趣的。…

16.Set、泛型、枚舉、反射、Class

Set Set集合是Collection集合的子接口&#xff0c;元素不能重復&#xff0c;只能有一個null&#xff0c;元素存放無序。 常用子類 HashSet TreeSet LinkedHashSet HashSet 其實底層就是HashMap&#xff0c;當我們構造一個HashSet對象&#xff0c;就是在 new HashSet(); …

23. 合并 K 個升序鏈表 - 力扣(LeetCode)

基礎知識要求&#xff1a; Java&#xff1a;方法、while循環、for循環、PriorityQueue類、if判斷 Python&#xff1a; 方法、while循環、for循環、heapq 模塊、if判斷 數據結構:隊列 題目&#xff1a; 給你一個鏈表數組&#xff0c;每個鏈表都已經按升序排列。 請你將所有鏈…

11.php-fpm模板(監控頁面取值)

php-fpm模板(監控頁面取值) 開啟監控頁面配置 #修改php配置文件 vim /etc/php-fpm.d/www.conf pm.status_path /php_status#修改nginx配置文件,添加到nginx配置文件中 vim /etc/nginx/conf.d/default.conflocation /php_status {root html;fastcgi_pass 127.0.…

肥貓“也能變“型男“?揭秘福派斯牛肉高脂貓糧的神奇效果!

福貓養成指南&#xff1a;福派斯牛肉高脂貓糧的優點與考慮因素 福派斯牛肉高脂貓糧&#xff0c;這款富含蛋白質與脂肪的貓糧&#xff0c;仿佛是貓咪世界中的美味佳肴&#xff0c;讓無數貓咪為之傾倒。然而&#xff0c;這款貓糧的利與弊&#xff0c;你是否都了解呢&#xff1f;接…

AI模型部署實戰:利用OpenCV的CUDA模塊加速視覺模型部署流程

本文首發于公眾號【DeepDriving】&#xff0c;歡迎關注。 一. 前言 我在之前的文章《AI模型部署實戰&#xff1a;利用CV-CUDA加速視覺模型部署流程》中介紹了如何使用CV-CUDA庫來加速視覺模型部署的流程&#xff0c;但是CV-CUDA對系統版本和CUDA版本的要求比較高&#xff0c;在…

大模型介紹

大模型通常指的是參數量超過億級別&#xff0c;甚至千億級別的深度學習模型。這類模型能夠處理更加復雜的任務&#xff0c;并在各項基準測試中取得了優異的成績。大模型在自然語言處理、計算機視覺、推薦系統等領域都取得了顯著的成果。 大模型的主要優勢在于其強大的表征能力&…

k8s的核心組件etcd功能詳解【含etcd各類參數詳細說明】

etcd 是 Kubernetes 中的一個關鍵組件&#xff0c;用于存儲集群的配置信息、狀態和元數據。它通常作為 Kubernetes 集群的數據存儲后端&#xff0c;為其他組件提供可靠的分布式鍵值存儲服務。下面我會詳細介紹 etcd 的功能以及常見的參數&#xff0c;以及如何配置和使用 etcd。…

Linux實驗 Shell編程

實驗目的&#xff1a; 熟練掌握Shell程序的建立與執行&#xff1b;掌握Shell變量的兩種類型&#xff08;Shell環境變量和用戶自定義變量&#xff09;及其用法&#xff1b;掌握Shell中的特殊字符、算術與邏輯運算&#xff1b;掌握Shell中輸入輸出命令&#xff1b;掌握Shell程序…

在Windows環境下安裝CPU版的PyTorch

PytTorch是基于Python開發的&#xff0c;首先需要安裝Python&#xff0c;Python的安裝很簡單&#xff0c;這里不再贅述。而 Windows用戶能直接通過conda、pip和源碼編譯三種方式來安裝PyTorch。 打開PyTorch官網&#xff08;PyTorch&#xff09;&#xff0c;在主頁中根據自己的…

基于OpenCV年齡與性別識別系統

深入解析基于OpenCV年齡與性別識別系統 在這篇博客中&#xff0c;我們將詳細解析一個使用OpenCV進行年齡和性別識別的Python腳本。這個腳本展示了如何利用深度學習模型&#xff0c;從視頻或圖像中檢測人臉并預測每個人臉的年齡和性別。 1. 導入必要的模塊 import cv2 as cv …

ELK的詳解

ELK是由Elasticsearch、Logstash和Kibana三個開源軟件&#xff08;后來又新加了一個FileBeat&#xff09;組成的日志管理解決方案&#xff0c;這一組合在近年來得到了廣泛的關注和應用。以下是對這三個組件的詳細說明&#xff1a; Elasticsearch&#xff1a; Elasticsearch是…

nginx 負載均衡配置詳解

基于 ${nginx_home}/conf/nginx.conf 文件配置實現&#xff0c;如下&#xff1a; http {# 定義server地址upstream server_group {server 192.168.xxx.1:8080;server 192.168.xxx.2:8080;server 192.168.xxx.3:8080;}server {listen 80;location / {root html;index …

python數據分析——時間序列

時間序列 前言一、Datetime 模塊常用函數和數據結構的詳細解釋datetime模塊示例一示例二 二、時間運算示例一示例二示例三 三、時間序列分析自回歸(Autoregressive model/AR)模型示例 滑動平均(moving average model/MA)模型示例 自回歸滑動平均(Autoregressive moving average…

持續總結中!2024年面試必問 100 道 Java基礎面試題(四十五)

上一篇地址&#xff1a;持續總結中&#xff01;2024年面試必問 100 道 Java基礎面試題&#xff08;四十四&#xff09;-CSDN博客 八十九、在Java中&#xff0c;什么是線程局部變量&#xff08;ThreadLocal變量&#xff09;&#xff1f; 在Java中&#xff0c;ThreadLocal變量是…

企業微信hook接口協議,ipad協議http,發送鏈接的方式邀請成員進群

發送鏈接的方式邀請成員進群 參數名必選類型說明uuid是String每個實例的唯一標識&#xff0c;根據uuid操作具體企業微信 請求示例 {"uuid":"3240fde0-45e2-48c0-90e8-cb098d0ebe43","roomid":10696052955013729, "vids":[788130334…

Flutter 中的 CircleAvatar 小部件:全面指南

Flutter 中的 CircleAvatar 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;CircleAvatar 是一個用于顯示頭像的圓形控件&#xff0c;通常包含一個圖標、圖片或者一個簡單的文本字符。它在設計上與 Material Design 指南中的頭像規范相匹配&#xff0c;常用于展示用戶信…

C# 常用匯總

時間處理 public static class DateTimeHelper{/// <summary>/// 獲取當前時間戳&#xff08;Unix時間戳&#xff09; /// </summary>/// <returns></returns>public static long GetCurrentUnixTimestamp(){DateTimeOffset offset DateTimeOffset.…

Qt---文件系統

一、基本文件操作 1. QFile對文件進行讀和寫 QFile file( path 文件路徑) 讀&#xff1a; file.open(打開方式) QlODevice::readOnly 全部讀取->file.readAll()&#xff0c;按行讀->file.readLine()&#xff0c;atend()->判斷是否讀到文件尾 …

Java網絡編程基礎

Java網絡編程基礎主要涉及進程間通信、網絡通信協議、IP地址和端口以及Java提供的網絡應用編程接口等核心概念。 進程間通信是Java網絡編程的基礎。進程是運行中的程序&#xff0c;而進程間通信則是指不同進程之間進行數據交換和共享信息的過程。在Java中&#xff0c;進程間的…