C++-->stl: list的使用

前言list的認識

list是可以在固定時間(O(1))內在任意位置進行插入和刪除的序列式容器,并且該容器可以前后雙向迭代。
2. list的底層是雙向鏈表結構,雙向鏈表中每個元素存儲在互不相關的獨立節點中,在節點中通過指針指向(當然有一個哨兵位 就是說頭節點)
其前一個元素和后一個元素。
3. listforward_list非常相似:最主要的不同在于forward_list是單鏈表,只能向前迭代,已讓其更簡單高(list是doubly list的接口 forward_list是單鏈表的接口)
效。
4. 與其他的序列式容器相比(arrayvectordeque)list通常在任意位置進行插入、移除元素的執行效率 更好。
5. 與其他序列式容器相比,listforward_list最大的缺陷是不支持任意位置的隨機訪問,比如:要訪問list 的第6個元素,必須從已知的位置(比如頭部或者尾部)迭代到該位置,在這段位置上迭代需要線性的時間? (需要創建一個結點去遍歷,比隨機訪問效率低)
? ?開銷;list還需要一些額外的空間,以保存每個節點的相關聯信息(對于存儲類型較小元素的list來說這不合適 可能是一個重要的因素

1?list的構造
常用的構造函數

default (1)

默認構造)

explicit list (const allocator_type& alloc = allocator_type());

? ? ? fill (2)

?n個val值填充

explicit list (size_type n, const value_type& val = value_type(),const allocator_type& alloc = allocator_type());

range (3)

? ?迭代器構造

template <class InputIterator>list (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());

copy (4)

拷貝構造

list (const list& x);
參考代碼 :?
? ?
void print_list(list<int>& list1)
{list<int>::iterator it = list1.begin();while (it != list1.end()){cout << *it;it++;}cout << endl;}
void construct_test()
{list<int>list_1;// 空構造list<int>list_2(20,0);// n  vallist<int>::iterator it = list_2.begin();  // 迭代器構造 list<int> th(list_2.begin(),list_2.end());// 不支持的寫法 list<int> th(list_2.begin(),list_2.begin()+4);// 因為list的迭代器不支持隨機訪問哦 其實本質上是因為只給迭代器封裝了++的操作 int arr[] = {1,2,3,4,5,6};list<int>four(arr,arr+4);// 這也是迭代器構造 數組肯定是可以通過下標 隨機訪問啦 // 拷貝構造//list<int> five = four;list<int> five(four);print_list(five);}

2. list的迭代器?

? ? list的圖解?

迭代器的理解:

??
? 這個迭代器的內部封裝可以大致這么理解:
? ? 肯定是對node的操作,封裝node的移動,有++,--以及!=? ?判斷倆個迭代器是否相等就這樣就很常見,封裝的目的很簡單,就是為了統一容器的操作哦!。
? ? 后期博客我會更新其中的模擬實現這是很有意思的:
? ?內部是沒有封裝+某個數的?
? ?所以之前例子中指出 像這樣的 list<int>::iterator(it,it+3);? 是不被允許的哦!
總之因為list的底層容器是雙向鏈表,每個節點地址之間是不連續的,所以我們為了統一容器操作就封裝迭代器了。
迭代器使用:代碼實例:
void iterator_test() {int arr[] = { 1,2,3,4,5,6 };list<int>four(arr, arr + 5);// 用迭代器遍歷four這個鏈表list<int>::iterator it = four.begin();// 正向迭代器list<int>::reverse_iterator rit = four.rbegin();// 反向迭代器while (it != four.end()){cout << *it;it++;}cout << endl;while (rit != four.rend()){cout << *rit;rit++;}cout << endl;}
輸出:12345? ?
? ? ? ? ? ?54321

doubly list的圖解

? ?這里只標出了 node之間指針的關系,這里值得注意的就是如何實現雙向循環的,就是創建一個頭節點,頭節點作用就是用來很方便的實現增刪查改(減少判空這個策略數據結構中可以多了解理解) 總之就是讓頭節點的pre指向尾節點,尾節點的next指向頭節點。 總之頭節點是不存放有效數據的! 所以下面我說說迭代器遍歷的問題!

?list迭代器遍歷的理解:?

? ? ? 顯然 list<T>iterator:: begin 指向的是頭節點的下一個位置,node結構體中總是存放的是頭節點,所以需要遍歷的時候需要總是從頭節點開始一一遍歷,而不是隨機訪問。?
? ? 判斷到尾部的方法有很多一個是根據size,以及cur節點的遍歷到了頭節點了。

3. list element access(元素獲取)

? ? ?list的獲取常用的就是一個是front? 和 back? 雙向鏈表根據頭節點實現起來很方便的。

? ? ?

3.1 reference front()? 和reference back的使用
? ? ? ? 這個list的front的成員函數,簡單來說就是返回一個頭節點的元素引用。?
這里的referrence其實是一個typedef,這個在庫里面實現是很常見的? 可以這樣理解:
typedef reference T;
? back同理如上。
? ?
// list::front
#include <iostream>
#include <list>int main ()
{std::list<int> mylist;mylist.push_back(77);mylist.push_back(22);// now front equals 77, and back 22mylist.front() -= mylist.back();std::cout << "mylist.front() is now " << mylist.front() << '\n';return 0;
}

輸出: 55

4. list modified 元素修改

? ? list常用的修改方面的有:? 頭插,頭刪,尾刪,尾插,還有指定位置刪除,和指定位置插入,還有指定尾插刪除, 以及swap (經常被用于去寫構造函數的還有拷貝構造)

4.1 push_front 和pop_front

實現:
// list::push_front
#include <iostream>
#include <list>int main ()
{std::list<int> mylist (2,100);         // two ints with a value of 100mylist.push_front (200);mylist.push_front (300);std::cout << "mylist contains:";for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

實現:
// list::pop_front
#include <iostream>
#include <list>int main ()
{std::list<int> mylist;mylist.push_back (100);mylist.push_back (200);mylist.push_back (300);std::cout << "Popping out the elements in mylist:";while (!mylist.empty()){std::cout << ' ' << mylist.front();mylist.pop_front();}std::cout << "\nFinal size of mylist is " << mylist.size() << '\n';return 0;
}

4.2 push_back和pop_front?

? ? 尾插和尾刪 返回值都是void注意哦
??
// list::push_back
#include <iostream>
#include <list>int main ()
{std::list<int> mylist;int myint;std::cout << "Please enter some integers (enter 0 to end):\n";do {std::cin >> myint;mylist.push_back (myint);} while (myint);std::cout << "mylist stores " << mylist.size() << " numbers.\n";return 0;
}

?

// list::pop_back
#include <iostream>
#include <list>int main ()
{std::list<int> mylist;int sum (0);mylist.push_back (100);mylist.push_back (200);mylist.push_back (300);while (!mylist.empty()){sum+=mylist.back();mylist.pop_back();}std::cout << "The elements of mylist summed " << sum << '\n';return 0;
}

4.3 insert

? 在指定位置(用迭代器哦) 插入一個元素,
? ? ?插入n個val 在指定位置
? 在指定位置插入一個范圍迭代器區間的元素

void insert_test() {int arr[] = { 1,2,3,4,5 };//    1  2  3  4  5int arr1[] = { 11,12,13,14,15 };//    11  12  13  14  15vector<int>v1(arr,arr+5);list<int> mylist(arr1,arr1+5);     //     !list<int>::iterator it = mylist.begin();it++;mylist.insert(it,10);// 迭代器可能存在失效的問題 所以這里一定要給it重賦值   print_list(mylist);// n valit = mylist.begin();it++;mylist.insert(it, 10,1);print_list(mylist);//  范圍插入it = mylist.begin();it++;mylist.insert(it, v1.begin()+2, v1.end());print_list(mylist);}
輸出:11 10 12 13 14 15
11 1 1 1 1 1 1 1 1 1 1 10 12 13 14 15
11 3 4 5 1 1 1 1 1 1 1 1 1 1 10 12 13 14 15

4.4 erase 刪除

?傳遞的參數是list的迭代器,指定位置刪除和指定的迭代器范圍區間的元素刪除。

std:: iterator& advance(iterator,len) 這是庫里的移動迭代器的函數

// erasing from list
#include <iostream>
#include <list>int main ()
{std::list<int> mylist;std::list<int>::iterator it1,it2;// set some values:for (int i=1; i<10; ++i) mylist.push_back(i*10);// 10 20 30 40 50 60 70 80 90it1 = it2 = mylist.begin(); // ^^advance (it2,6);            // ^                 ^++it1;                      //    ^              ^it1 = mylist.erase (it1);   // 10 30 40 50 60 70 80 90//    ^           ^it2 = mylist.erase (it2);   // 10 30 40 50 60 80 90//    ^           ^++it1;                      //       ^        ^--it2;                      //       ^     ^mylist.erase (it1,it2);     // 10 30 60 80 90//        ^std::cout << "mylist contains:";for (it1=mylist.begin(); it1!=mylist.end(); ++it1)std::cout << ' ' << *it1;std::cout << '\n';return 0;
}

5. 迭代器失效問題

? ?我們之前說過迭代器的實現可以理解為一個封裝了node的移動和判斷的類。? 這里的數據存放是node,所以本質上還是用node*指向了一個節點,所以在list中只要該節點不刪除,這個節點依然存在。?
? 在list中插入不會導致迭代器失效,因為這個節點并沒有被銷毀(vector中的迭代器失效是因為他們的內存是連續的,當擴容的時候可能導致舊內存被銷數據被移動到新內存)但是list的底層是雙向循環鏈表,內存之間都是用指針(地址)連接起來的,不用在乎是否連續,你不主動銷毀內存是不會被銷毀的。
? ?所以只有當刪除的時候才會被銷毀。

談談erase和insert的返回值

? ?erase:
iterator erase (iterator position);
iterator erase (iterator first, iterator last); 

insert:

single element (1)
iterator insert (iterator position, const value_type& val);
fill (2)
void insert (iterator position, size_type n, const value_type& val);
range (3)
template <class InputIterator>void insert (iterator position, InputIterator first, InputIterator last);
insert:大體上分為兩,一種是插入一個元素,一個是插入多個元素。
返回值:簡單理解就是返回插入元素后的下一個位置的元素
erase則是返回刪除元素的下一個位置
處理迭代器失效: 就是重新賦值給迭代器:
錯誤實例 沒有重新賦值?
修正:?
? ?代碼:?
void TestListIterator1()
{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()){// erase()函數執行后,it所指向的節點已被刪除,因此it無效,在下一次使用it時,必須先給//其賦值it =l.erase(it);++it;}
}

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

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

相關文章

本地WSL部署接入 whisper + ollama qwen3:14b 總結字幕

1. 實現功能 M4-1 接入 whisper ollama qwen3:14b 總結字幕 自動下載視頻元數據如果有字幕&#xff0c;只下載字幕使用 ollama 的 qwen3:14b 對字幕內容進行總結 2.運行效果 source /root/anaconda3/bin/activate ytdlp &#x1f50d; 正在提取視頻元數據… &#x1f4dd; 正在…

《Linux運維總結:Shell腳本高級特性之變量間接調用》

總結&#xff1a;整理不易&#xff0c;如果對你有幫助&#xff0c;可否點贊關注一下&#xff1f; 更多詳細內容請參考&#xff1a;Linux運維實戰總結 一、變量間接調用 在Shell腳本中&#xff0c;變量間接調用是一種高級特性&#xff0c;它允許你通過另一個變量的值來動態地訪問…

ABP VNext + Akka.NET:高并發處理與分布式計算

ABP VNext Akka.NET&#xff1a;高并發處理與分布式計算 &#x1f680; 用 Actor 模型把高并發寫入“分片→串行化”&#xff0c;把鎖與競態壓力轉回到代碼層面的可控順序處理&#xff1b;依托 Cluster.Sharding 橫向擴容&#xff0c;Persistence 宕機可恢復&#xff0c;Strea…

[激光原理與應用-250]:理論 - 幾何光學 - 透鏡成像的優缺點,以及如克服缺點

透鏡成像是光學系統中應用最廣泛的技術&#xff0c;其通過折射原理將物體信息轉換為圖像&#xff0c;但存在像差、環境敏感等固有缺陷。以下是透鏡成像的優缺點及針對性改進方案&#xff1a;一、透鏡成像的核心優點高效集光能力透鏡通過曲面設計將分散光線聚焦到一點&#xff0…

測試匠談 | AI語音合成之大模型性能優化實踐

「測試匠談」是優測云服務平臺傾心打造的內容專欄&#xff0c;匯集騰訊各大產品的頂尖技術大咖&#xff0c;為大家傾囊相授開發測試領域的知識技能與實踐&#xff0c;讓測試工作變得更加輕松高效。 本期嘉賓介紹 Soren&#xff0c;騰訊TEG技術事業群質量工程師&#xff0c;負責…

用天氣預測理解分類算法-從出門看天氣到邏輯回歸

一、生活中的決策難題&#xff1a;周末郊游的「天氣判斷」 周末計劃郊游時&#xff0c;你是不是總會打開天氣預報反復確認&#xff1f;看到 "25℃、微風、無雨" 就興奮收拾行李&#xff0c;看到 "35℃、暴雨" 就果斷取消計劃。這個判斷過程&#xff0c;其…

HTTPS服務

HTTPS服務 一、常見的端口 http ------ 80 明文 https ------ 443 數據加密 dns ------ 53 ssh ------ 22 telent ------ 23 HTTPS http ssl或者tls &#xff08;安全模式&#xff09; 二、原理&#xff1a; c&#xff08;客戶端…

【Android筆記】Android 自定義 TextView 實現垂直漸變字體顏色(支持 XML 配置)

Android 自定義 TextView 實現垂直漸變字體顏色&#xff08;支持 XML 配置&#xff09; 在 Android UI 設計中&#xff0c;字體顏色的漸變效果能讓界面看起來更加精致與現代。常見的漸變有從左到右、從上到下等方向&#xff0c;但 Android 的 TextView 默認并不支持垂直漸變。…

CANopen Magic調試軟件使用

一、軟件安裝與硬件連接1.1 系統要求操作系統&#xff1a;Windows 7/10/11 (64位)硬件接口&#xff1a;支持Vector/PEAK/IXXAT等主流CAN卡推薦配置&#xff1a;4GB內存&#xff0c;2GHz以上CPU1.2 安裝步驟運行安裝包CANopen_Magic_Setup.exe選擇安裝組件&#xff08;默認全選&…

前端css學習筆記3:偽類選擇器與偽元素選擇器

本文為個人學習總結&#xff0c;如有謬誤歡迎指正。前端知識眾多&#xff0c;后續將繼續記錄其他知識點&#xff01; 目錄 前言 一、偽類選擇器 1.概念 2.動態選擇器&#xff08;用戶交互&#xff09; 3.結構偽類 &#xff1a;first-child&#xff1a;選擇所有兄弟元素的…

深入探索 PDF 數據提取:PyMuPDF 與 pdfplumber 的對比與實戰

在數據處理和分析領域&#xff0c;PDF 文件常常包含豐富的文本、表格和圖形信息。然而&#xff0c;從 PDF 中提取這些數據并非易事&#xff0c;尤其是當需要保留格式和顏色信息時。幸運的是&#xff0c;Python 社區提供了多個強大的庫來幫助我們完成這項任務&#xff0c;其中最…

Springboot注冊過濾器的三種方式(Order 排序)

一、使用 Component Order&#xff08;簡單但不夠靈活&#xff09; 適用于全局過濾器&#xff0c;無需手動注冊&#xff0c;Spring Boot 會自動掃描并注冊。 Component Order(1) // 數字越小&#xff0c;優先級越高 public class AuthFilter implements Filter {Autowired /…

電腦硬件詳解

前幾天我的風扇轉的很快&#xff0c;而且cpu占用率很高&#xff0c;然后我在想怎么回事&#xff0c;然后就淺淺研究了一下電腦的硬件。 筆記本主板&#xff1a; 臺式機主板&#xff1a; 圖1&#xff1a; 圖2&#xff1a; 電腦硬件詳解 電腦的硬件是組成計算機系統的物理設…

力扣47:全排列Ⅱ

力扣47:全排列Ⅱ題目思路代碼題目 給定一個可包含重復數字的序列 nums &#xff0c;按任意順序 返回所有不重復的全排列。 思路 又是任意順序和所有不重復的排列&#xff0c;顯而易見我們要使用回溯的辦法。 首先是回溯的結束條件即新數組的長度等于nums的長度。這道題的難點…

學習筆記091——如何實現web登錄時,密碼復雜度校驗?(后端)

1、創建工具類 /*** 密碼復雜度校驗* param password 密碼*/ public static void validatePassword(String password) {// 至少8位if (password.length() < 8) {throw new IllegalArgumentException("密碼長度至少為8位");}// 包含大小寫字母if (!password.matche…

雪花算法snowflake分布式id生成原理詳解,以及對解決時鐘回撥問題幾種方案討論

一、前言在日趨復雜的分布式系統中&#xff0c;數據量越來越大&#xff0c;數據庫分庫分表是一貫的垂直水平做法&#xff0c;但是需要一個全局唯一ID標識一條數據或者MQ消息&#xff0c;數據庫id自增就顯然不能滿足要求了。因為場景不同&#xff0c;分布式ID需要滿足以下幾個條…

【PCB設計經驗】去耦電容如何布局?

0805 和 0603 以及更小 封裝的電容用作于對中高頻的去耦,其擺放位置是有要求的: 一、建議盡可能的靠近主控芯片的 電源管腳放置。 二、使用較寬和短的引線連接到電源和地過孔可以采用如下 圖 4–1 中的圖 ( 2 )、( 3)、 ( 4 )任意一種方式,避免使用長線或者較細的…

自動化運維實驗

目錄 一、實驗拓撲 二、實驗目的 三、實驗步驟 實驗思路&#xff1a; 代碼部分&#xff1a; 四、實驗結果&#xff1a; 一、實驗拓撲 二、實驗目的 利用python腳本&#xff0c;在本地&#xff0c;或者虛擬機里實現&#xff0c;設備CRC數量統計&#xff0c;并輸出成表格 三、實驗…

Wed前端第二次作業

一、作業1&#xff1a;完成自己學校的官網&#xff0c;動忘內容直接貼&#xff0c;至少三個不同的頁面1、界面1&#xff08;1&#xff09;相關代碼<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name&quo…

第5節 大模型分布式推理通信優化與硬件協同

前言 在分布式推理中,多設備(如GPU、CPU)之間的數據傳輸(通信)是連接計算的“橋梁”。如果通信效率低下,即使單設備計算能力再強,整體性能也會大打折扣。想象一下:如果工廠之間的物流卡車跑得比生產速度還慢,再多的工廠也無法提高整體產量。 本節將從最基礎的單設備內…