【C++】STL·List

1. list的介紹及使用

1.1list介紹

List文檔介紹

1.2 list的使用

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

1.2.1 list的構造

list<int>lt1(5);           構造空的list
list<int>lt2(3, 2);        構造的list中包含n個值為val的元素
list<int>lt3(lt2);         拷貝構造函數
int arr[] = { 1,2,3,4,5 };
list<int>lt4(arr, arr + 5);用[?rst, last)區間中的元素構造list

1.2.2 list iterator的使用

	lt1.begin();  返回第一個元素的迭代器  lt1.end();    返回最后一個元素下一個位置的迭代器lt1.rbegin(); 返回第一個元素的reverse_iterator, 即end位置lt1.rend();   返回最后一個元素下一個位置的reverse_iterator, 即begin位置

1.2.3 list capacity

	lt1.size();  返回list中有效節點的個數lt1.empty(); 檢測list是否為空,是返回true,否則返回false
1.2.4 list element access

	lt1.front(); 返回list的第一個節點中值的引用lt1.back();  返回list的最后一個節點中值的引用
1.2.5 list modi?ers

	lt1.push_back(1);			尾插lt1.push_front(1);			頭插lt1.pop_back();				尾刪lt1.pop_front();			頭刪lt1.insert(lt1.begin(), 1); 在list position 位置中插入值為val的元素lt1.erase(lt1.begin());		刪除list position位置的元素lt1.swap(lt2);				交換兩個list中的元素lt1.clear();				清空list中的有效元素
1.2.6 list的迭代器失效

迭代器失效即迭代器所指向的節點的無效,即該節點被刪除了。因為list的底層結構為帶頭結點的雙向循環鏈表,因此在list中進行插入時是不會導致list的迭代器失效的,只有在刪除時才會失效,并且失效的只是指向被刪除節點的迭代器,其他迭代器不會受到影響。

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時,必須先給其賦值l.erase(it);++it;}
}
// 改正
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);}
}

2. list的模擬實現

2.1 模擬實現list

#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace XiaoHai
{template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& x = T()):_data(x), _next(nullptr), _prev(nullptr){ }};template<class T, class ref, class Ptr>struct Reverse_iterator{Iterator _it;typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){iterator tmp(_it);--tmp;return *tmp;}Ptr operator->(){return &(operator*());}self operator++(int){self tmp(_it);--_it;return *tmp;}self operator--(int){self tmp(_it);++_it;return *tmp;}self operator++(){--_it;return *tmp;}self operator--(){++_it;return *tmp;}bool operator!=(const Self& s){return _it != s._it;}};template<class T,class ref,class Ptr>struct __list_iterator{typedef list_node<T> Node;typedef __list_iterator<T,ref,Ptr> self;Node* _node;__list_iterator(Node* node):_node(node){ }ref& operator*(){return _node->_data;}T* operator->(){return &_node->_data;}self& operator++(){_node = _node->_next;return *this;}self& operator++(int){__list_iterator<T>tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self& operator--(int){__list_iterator<T>tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const __list_iterator<T>& it)const{return _node != it._node;}bool operator ==(const __list_iterator<T>& it)const{return !(_node != it._node);}};template<class T>class list{typedef list_node<T> Node;public:typedef __list_iterator<T,T&,T*> iterator;typedef __list_iterator<T,const T&,const T*> const_iterator;iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator begin() const{return iterator(_head->_next);}const_iterator end() const{return iterator(_head);}void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;}list(){empty_init();}//lt2(lt1)list(const list<T>&lt){empty_init();for (const auto& e:lt){push_back(e);}}list(initializer_list<int>il){empty_init();for (const auto& e : il){push_back(e);}}void swap(list<T>&lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}//lt1 = lt2list<T>& operator=(const list<T>* lt){swap(lt);return *this;}/*list<T>& operator=(const list<T>* lt){if (this != &lt){clear();for (const auto& e : il){push_back(e);}}return *this;}*/~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void insert(iterator pos, const T& val){Node* cur = pos._node;Node* newnode = new Node(val);Node* prev = cur->_prev;//prev newnode curprev->_next = newnode;newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;++_size;}iterator& erase(iterator pos){Node* cur = pos._node;Node* next = cur->_next;Node* prev = cur->_prev;//prev (cur) nextprev->_next = next;next->_prev = prev;delete cur;--_size;return iterator(next);}size_t size(){return _size;}private:Node* _head;size_t _size = 0;};
}

2.2 list的反向迭代器

通過前面例子知道,反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++, 因此反向迭代器的實現可以借助正向迭代器,即:反向迭代器內部可以包含一個正向迭代器,對正向迭代器的接口進行包裝即可。

	template<class T, class ref, class Ptr>struct Reverse_iterator{Iterator _it;typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){iterator tmp(_it);--tmp;return *tmp;}Ptr operator->(){return &(operator*());}self operator++(int){self tmp(_it);--_it;return *tmp;}self operator--(int){self tmp(_it);++_it;return *tmp;}self operator++(){--_it;return *tmp;}self operator--(){++_it;return *tmp;}bool operator!=(const Self& s){return _it != s._it;}};

3. list與vector的對比

vector與list都是STL中非常重要的序列式容器,由于兩個容器的底層結構不同,導致其特性以及 應用場景不同

vectorlist
底層結構動態順序表,一段連續空間帶頭結點的雙向循環鏈表
隨機訪問支持隨機訪問,訪問某個元素效率O(1)不支持隨機訪問,訪問某個元素效率O(n)
插入和刪除尾插效率高,任意位置插入和刪除效率低,需要搬移元素,時間復雜度為O(N),插入時有可能需要增容,增容: 開辟新空間,拷貝元素,釋放舊空間,導致效率更低任意位置插入和刪除效率高, 不需要搬移元素,時間復雜度 為O(1)
空間利用率底層為連續空間,不容易造成內存碎片,空間利用率高,緩存利用率高底層節點動態開辟,小節點容易造成內存碎片,空間利用率 低,緩存利用率低
迭代器原生態指針對原生態指針(節點指針)進行封裝
迭代器失效插入操作如果導致底層空間重新開辟,則迭代器就會失效,刪除操作不光會導致指向被刪除元素的迭代器失效,刪除元素后面的迭代器也會失效插入元素不會導致迭代器失效,刪除元素時,只會導致當前迭代器失效,其他迭代器不受影響
使用場景需要高效存儲,支持隨機訪問,不關心插入刪除效率大量插入和刪除操作,不關心隨機訪問

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

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

相關文章

圖論2 圖的數據結構表示

目錄 一 圖的數據結構表示 1 鄰接矩陣&#xff08;Adjacency Matrix&#xff09; 2 鄰接表&#xff08;Adjacency List&#xff09; 3 邊列表&#xff08;Edge List&#xff09; 4 十字鏈表&#xff08;Orthogonal List / Cross-linked List, 十字鏈表&#xff09; 5 鄰接…

在Excel中刪除大量間隔空白行

在 Excel 中刪除大量間隔空白行&#xff0c;可使用定位空值功能來快速實現。以下是具體方法&#xff1a;首先&#xff0c;選中包含空白行的數據區域。可以通過點擊數據區域的左上角單元格&#xff0c;然后按住鼠標左鍵拖動到右下角最后一個單元格來實現。接著&#xff0c;按下快…

【C 學習】10-循環結構

“知道做不到就是不知道”一、條件循環1. while只要條件為真&#xff08;true&#xff09;&#xff0c;就會重復執行循環體內的代碼。while (條件) {// 循環體&#xff08;要重復執行的代碼&#xff09; }//示例 int i 1; while (i < 5) {printf("%d\n", i);i; …

音視頻的下一站:協議編排、低時延工程與國標移動化接入的系統實踐

一、引言&#xff1a;音視頻的基礎設施化 過去十年&#xff0c;音視頻的兩條主線清晰可辨&#xff1a; 娛樂驅動&#xff1a;直播、電商、短視頻把“實時觀看與互動”變成高頻日常。 行業擴展&#xff1a;教育、會議、安防、政務逐步把“可用、可管、可控”引入產業系統。 …

SAM-Med3D:面向三維醫療體數據的通用分割模型(文獻精讀)

1) 深入剖析:核心方法與圖示(Figure)逐一對應 1.1 單點三維提示的任務設定(Figure 1) 論文首先將3D交互式分割的提示形式從“2D逐片(每片1點,共N點)”切換為“體素級單點(1個3D點)”。Figure 1直觀對比了 SAM(2D)/SAM-Med2D 與 SAM-Med3D(1點/體) 的差異:前兩者…

【Spring】原理解析:Spring Boot 自動配置進階探索與優化策略

一、引言在上一篇文章中&#xff0c;我們對 Spring Boot 自動配置的基本原理和核心機制進行了詳細的分析。本文將進一步深入探索 Spring Boot 自動配置的高級特性&#xff0c;包括如何進行自定義擴展、優化自動配置的性能&#xff0c;以及在實際項目中的應用優化策略。同時&…

OpenCV:圖像直方圖

目錄 一、什么是圖像直方圖&#xff1f; 關鍵概念&#xff1a;BINS&#xff08;區間&#xff09; 二、直方圖的核心作用 三、OpenCV 計算直方圖&#xff1a;calcHist 函數詳解 1. 函數語法與參數解析 2. 基礎實戰&#xff1a;計算灰度圖直方圖 代碼實現 結果分析 3. 進…

docke筆記下篇

本地鏡像發布到阿里云 本地鏡像發布到阿里云流程 鏡像的生成方法 基于當前容器創建一個新的鏡像&#xff0c;新功能增強 docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]] OPTIONS說明&#xff1a; OPTIONS說明&#xff1a; -a :提交的鏡像作者&#xff1b; -m :提交時的說…

《大數據之路1》筆記2:數據模型

一 數據建模綜述 1.1 為什么要數據建模背景&#xff1a; 隨著DT時代的來臨&#xff0c;數據爆發式增長&#xff0c;如何對數據有序&#xff0c;有結構地分類組織額存儲是關鍵定義&#xff1a; 數據模型時數據組織和存儲的方法&#xff0c;強調從業務、數據存取、使用角度 合理存…

“量子能量泵”:一種基于并聯電池與電容陣的動態直接升壓架構

“量子能量泵”&#xff1a;一種基于并聯電池與電容陣的動態直接升壓架構摘要&#xff1a;本文揭示了一種革命性的高效電源解決方案&#xff0c;旨在徹底解決低電壓、大功率應用中的升壓效率瓶頸與電池一致性難題。該方案摒棄傳統磁性升壓拓撲&#xff0c;創新性地采用并聯電池…

DeepSeek實戰--自定義工具

1. 背景 當前已經有很多AI基礎平臺&#xff08;比如&#xff1a;扣子、Dify&#xff09;&#xff0c;用戶可以快速搭建Agent&#xff0c;那怎樣將已有的接口能力給大模型調用呢 &#xff1f; 今天我們來探索一個&#xff0c;非常高效、快捷的方案&#xff1a;將http接口做成Dif…

“移動零”思路與題解

給定一個數組 nums&#xff0c;編寫一個函數將所有 0 移動到數組的末尾&#xff0c;同時保持非零元素的相對順序。請注意 &#xff0c;必須在不復制數組的情況下原地對數組進行操作。思路講解&#xff1a;舉例如下&#xff1a;實現代碼是&#xff1a;class Solution { public:v…

關于行內元素,行內塊元素和塊級元素

1、什么是行內元素&#xff0c;什么是行內塊元素&#xff0c;什么是塊級元素行內元素的特點&#xff1a;不獨占一行&#xff0c;相鄰元素會在同一行顯示&#xff0c;直到一行排不下才換行。寬度和高度由內容本身決定&#xff0c;無法通過width&#xff0c;height手動設置&#…

?絡請求Axios的概念和作用

Axios 是一個基于 ??Promise?? 的輕量級、高性能 ??HTTP 客戶端庫??&#xff0c;主要用于在瀏覽器和 Node.js 環境中發起 HTTP 請求&#xff08;如 GET、POST、PUT、DELETE 等&#xff09;。它通過簡潔的 API 和強大的功能&#xff0c;簡化了前端與后端之間的數據交互過…

在AgentScope中實現結構化輸出

在AgentScope中實現結構化輸出 概述 在AgentScope框架中&#xff0c;結構化輸出功能允許開發者定義明確的輸出模式&#xff0c;確保AI模型的響應符合預期的格式和約束。本教程將介紹如何使用AgentScope的structured_model參數來實現結構化輸出。 結構化輸出的優勢 數據一致性&a…

Linux 磁盤I/O高占用進程排查指南:從定位到分析的完整流程

在Linux服務器運維工作中&#xff0c;磁盤I/O瓶頸是導致系統性能下降的常見原因之一。當服務器出現響應緩慢、應用卡頓等問題時&#xff0c;及時定位并解決高I/O占用進程就顯得尤為重要。本文將從核心思路出發&#xff0c;通過“確認問題-定位磁盤-鎖定進程-深入分析”四個步驟…

解決React中通過外部引入的css/scss/less文件更改antDesign中Modal組件內部的樣式不生效問題

不生效原因Ant Design 的 Modal 默認通過 ReactDOM.createPortal 掛在 <body> 下&#xff0c;與你的組件樹平級&#xff0c;所以寫在 .module.css / scoped less 里的選擇器根本匹配不到它&#xff0c;就算寫全局樣式&#xff0c;也可能因為權重不足或異步掛載時機而“看…

day41 51單片機最小系統、GPIO控制、時序邏輯器件(74HC138/595)與LED點陣驅動原理

day41 51單片機最小系統、GPIO控制、時序邏輯器件&#xff08;74HC138/595&#xff09;與LED點陣驅動原理一、嵌入式系統基礎概念 1.1 嵌入式系統定義先設計硬件&#xff0c;基于硬件設計軟件實現一個具體的功能 —— 專用的計算機系統硬件/軟件可剪裁&#xff1a;根據功能需求…

html列表總結補充

1.有序列表的type屬性不同的type值表示不同的排序標號1 表示列表項目用數字標號&#xff08;1,2,3...&#xff09; 1 a 表示列表項目用小寫字母標號&#xff08;a,b,c...&#xff09; 2 A 表示列表項目用大寫字母標號&#xff08;A,B,C...&#xff09; 3 i 表示列表項目用小寫羅…

smartctl Current_Pending_Sector 硬盤待處理扇區

smartctl -a /dev/sdae當前值: 312 個待處理扇區 嚴重警告信號&#xff0c;硬盤發現了 312 個可疑扇區&#xff0c;正在等待重新分配 197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 312讀取錯誤頻發 錯誤計數: 38 次 ATA 錯誤 …