list 介紹 及 底層

list的相關文檔:list - C++ Reference

一、list的介紹及使用

list中的接口比較多,此處類似,只需要掌握如何正確的使用,然后再去深入研究背后的原理,已達到可擴展的能力。以下為list中一些常見的重要接口。我們庫里的list 是一個帶頭雙向循環鏈表 。?

1.1 list 的構造

1.2. list 迭代器的使用?

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

?遍歷鏈表 , 與vector和string 不同的是 , list 不支持 [ ] , 僅支持迭代器和范圍 for 遍歷鏈表 。

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int>lt2 = { 1,2,3,4,5 };list<int>::iterator it1 = lt1.begin();while (it1 != lt1.end()){cout << *it1 << " ";++it1;}cout << endl;for (auto& e : lt2){cout << e << " ";}cout << endl;return 0;
}

?1.3 list modifiers

1)emplace_back 和 push_back 都能實現尾插一個數據 , 有什么區別 ??

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<list>
using namespace std;class Pos
{
public:Pos(int row,int col):_row(row),_col(col){}
private:int _row;int _col;
};int main()
{list<Pos> lt;Pos p1(1, 1);lt.push_back(p1);lt.push_back(Pos(2, 2));lt.push_back({3,3});lt.emplace_back(p1);lt.emplace_back(Pos(2, 2));//lt.emplace_back({ 3,3 });lt.emplace_back(3, 3);return 0;
}

補充 : 單參數的構造函數 , 支持隱式類型轉化?

?

?2)刪除指定元素

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<list>
using namespace std;int main()
{list<int> lt1 = { 1,2,3,4,5 };for (auto e : lt1){cout << e << " ";}cout << endl;int x;cin >> x;auto it = find(lt1.begin(), lt1.end(), x);if (it != lt1.end()){lt1.erase(it);}for (auto e : lt1){cout << e << " ";}cout << endl;return 0;
}

1.4?Operations

1)merge : 合并

?

?2)unique : 去重? , 前提:有序

3)splice : 把一個鏈表的值轉移到另一個鏈表

?可以用來實現類似LRU(最近最少使用)的算法:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<list>
using namespace std;//LRU
int main()
{list<int> lt1 = { 1,2,3,4,5 };for (auto e : lt1){cout << e << " ";}cout << endl;int x;while (cin >> x){auto pos = find(lt1.begin(), lt1.end(), x);if (pos != lt1.end()){lt1.splice(lt1.begin(), lt1, pos);}for (auto e : lt1){cout << e << " ";}cout << endl;}return 0;
}

4)sort : 排序

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<list>
using namespace std;int main()
{list<int> lt1 = { 15,2,31,14,15 };for (auto e : lt1){cout << e << " ";}cout << endl;lt1.sort();for (auto e : lt1){cout << e << " ";}cout << endl;greater<int> gt;lt1.sort(gt);for (auto e : lt1){cout << e << " ";}cout << endl;return 0;
}

?為了簡化,我們一般按照下面的寫法 ,傳仿函數 :

?

?為什么庫里面有sort , list 還要實現一個sort , 難道不會是多次一舉嗎?

我們可以看到 , 不是list 不想用 , 是list 根本用不了 。 這就和迭代器的功能分類有關了。

?

?雖然,算法庫的sort 是一個模板,但是也很明顯的告訴了你 , 傳的要是隨機迭代器 。

二、list 底層

模板不支持分離成兩個文件 , 這里我們僅創建 list.h?

list 的底層很深刻的體現了封裝的優點:

  • 三者的角色分工
    • 節點(Node)?- 數據的 "容器" :?存儲實際的數據,以及連接其他節點的指針(前向和后向指針)
    • 迭代器(Iterator)?- 數據的 "導航員" :?提供訪問節點數據的統一方式屏蔽底層節點的實現細節
    • list 類?- 整個鏈表的 "管理者" :?負責整體的創建、銷毀、插入、刪除等操作,維護鏈表的完整性

  • 封裝的意義

    • 分離關注點

      • 節點只關心數據存儲和連接
      • 迭代器只關心如何訪問數據
      • list 類只關心整體管理
      • 這樣每個部分可以獨立修改,不會互相影響
    • 隱藏實現細節
      • 用戶不需要知道節點如何定義
      • 不需要知道迭代器如何移動
      • 只需要調用 list 提供的接口即可
    • 統一訪問方式???????
      • 無論是 list、vector 還是其他容器,都可以用類似的迭代器方式訪問
      • 使得算法可以通用(如 sort、find 等)
    • 提高安全性???????
      • 防止用戶直接操作節點指針導致的錯誤
      • 迭代器會自動處理邊界檢查等問題

?

2.1 list 節點類

1. ( 慣例 )?如果成員變量 和 成員函數 全部是公有的 , 一般用 struct 。既有公有 又有 私有 , 則用class

2. 如果把節點類放公有 , 不是會不安全 ? 能被任意修改 ?

節點類雖然是公開的 , 但是 是隱形的封裝 , 對 list 才有用 , 在使用 list 的接口的時候 , 其實我們并不會知道它底層是雙向帶頭鏈表 , 也不知道成員變量的具體變量名(不同平臺的變量名會不同),所以是安全的 , 在list 的增刪查改的時候 , 會高頻的調用list 的節點,所以直接放成struct?

	//慣例
//全部是公用,一般用structtemplate<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& x = T()):_data(x), _prev(nullptr), _next(nullptr){}};

?缺省值給匿名對象 , 因為類型是不確定的 , 給字面量 不合適 。

2.2 list 迭代器

1.? ?原生指針已經不夠用了 ;所以list 的迭代器是 類封裝指針 , 重載運算符 , 模擬指針行為

2.? 使用struct , 因為需要頻繁訪問內部成員 , 不建議用訪問限定符限制 。

3. 容器迭代器設計思路體現了封裝 :屏蔽底層實現細節,屏蔽各容器結構差異 , 本質封裝底層細節 和 差異 ,提供統一的訪問方式 。

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;}Ptr operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}//返回局部對象就不能再使用引用返回了Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}
};

?

2.3 list 類

1)insert:

返回 iterator ;由于不需要擴容 , 所以不存在迭代器失效的問題

		iterator insert(iterator pos, const T& val){Node* cur = pos._node;Node* newnode = new Node(val);Node* prev = cur->_prev;//prev newnode curnewnode->_prev = prev;newnode->_next = cur;prev->_next = newnode;cur->_prev = newnode;return iterator(newnode);}

復用insert 實現頭插和尾插 :

		void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}

2)erase :

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

注意 : 刪除唯獨不能刪除哨兵位的頭結點 !!!

	iterator erase(iterator pos){assert(pos != end());Node* del = pos._node;Node* prev = del->_prev;Node* next = del->_next;//prev del nextprev->_next = next;next->_prev = prev;delete del;return iterator(next);}

?復用erase 實現頭刪 和 尾刪 :

		void pop_back(){erase(--end());}void pop_front(){erase(begin());}

3) 析構

		~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}

clear 是清理資源 , 但是結構依舊保持 。 (注意 : list 的erase 會導致迭代器失效的問題 , 需要更新一下迭代器 。 ) 析構 不僅清理資源 , 同時會把頭結點給刪除了 。

4)拷貝構造 :?

		//拷貝構造//lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}

5)賦值重載:

//賦值重載
//lt2 = lt3
list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}void swap(list<T>& tmp)
{std::swap(_head, tmp._head);
}

6)所有代碼:list.h

#pragma once
#include<assert.h>namespace LF
{//慣例
//全部是公用,一般用structtemplate<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& x = T()):_data(x), _prev(nullptr), _next(nullptr){}};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;}Ptr operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}//返回局部對象就不能再使用引用返回了Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}};//template<class T>//struct list_const_iterator//{//	typedef list_node<T> Node;//	typedef list_const_iterator<T> Self;//	Node* _node;//	list_const_iterator(Node* node)//		:_node(node)//	{}//	const T& operator*()//	{//		return _node->_data;//	}//	const T* operator->()//	{//		return &_node->_data;//	}//	Self& operator++()//	{//		_node = _node->_next;//		return *this;//	}//	Self& operator--()//	{//		_node = _node->_prev;//		return *this;//	}//	Self operator++(int)//	{//		Self tmp(*this);//		_node = _node->_next;//		return tmp;//	}//	Self operator--(int)//	{//		Self tmp(*this);//		_node = _node->_prev;//		return tmp;//	}//	bool operator!=(const Self& s)//	{//		return _node != s._node;//	}//};template<class T>class list{typedef list_node<T> Node;public://typedef list_iterator<T> iterator;//typedef list_const_iterator<T> const_iterator;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 const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}void empty_init(){_head = new Node();_head->_prev = _head;_head->_next = _head;}list(){empty_init();}~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}//n個val構造list(size_t n, const T& val = T()){empty_init();for (size_t i = 0; i < n; i++){push_back(val);}}//拷貝構造//lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}//賦值重載//lt2 = lt3list<T>& operator=(list<T> lt){swap(lt);return *this;}void swap(list<T>& tmp){std::swap(_head, tmp._head);}//void push_back(const T& x)//{//	Node* new_node = new Node(x);//	Node* tail = _head->_prev;//	new_node->_next = _head;//	new_node->_prev = tail;//	_head->_prev = new_node;//	tail->_next = new_node;//}void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}iterator insert(iterator pos, const T& val){Node* cur = pos._node;Node* newnode = new Node(val);Node* prev = cur->_prev;//prev newnode curnewnode->_prev = prev;newnode->_next = cur;prev->_next = newnode;cur->_prev = newnode;return iterator(newnode);}iterator erase(iterator pos){assert(pos != end());Node* del = pos._node;Node* prev = del->_prev;Node* next = del->_next;//prev del nextprev->_next = next;next->_prev = prev;delete del;return iterator(next);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}private:Node* _head;};
}

2.4 list 和 vector的對比

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

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

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

相關文章

HCIP MGRE實驗

一、實驗要求 1、R5為ISP&#xff0c;只能進行IP地址配置&#xff0c;其所有地址均配為公有Ip地址; 2、 R1和R5間使用PPP的PAP認證&#xff0c;R5為主認證方&#xff1b; R2與R5之間使用PPP的CHAP認證&#xff0c;R5為主認證方; R3與R5之間使用HDLC封裝; 3、R2、R3構建一…

基于PyTorch的多視角二維流場切片三維流場預測模型

基于PyTorch的多視角二維流場切片三維流場預測模型 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家&#xff0c;覺得好請收藏。點擊跳轉到網站。 1. 引言 計算流體動力學(CFD)在工程設計和科學研究中扮演…

全新輕量化PHP網盤搜索引擎系統源碼

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 全新輕量化PHP網盤搜索引擎系統源碼 基于PHPMYSQL開發 一、多樣篩選功能&#xff1a;網站支持5類篩選功能&#xff0c;包括默認搜索、網盤類型、文件大小、時間排序以及網盤來源&#x…

C study notes[3]

文章目錄operatonsloopsreferencesoperatons the fundamental operators such as ,-,* in C language can be simply manipulated. int sum 5 3; // sum 8 int difference 10 - 4; // difference 6 int product 6 * 7; // product 42the operator / was left to in…

練習實踐-基礎設施-文件共享-windows和linux之間的文件共享-smb服務搭建

參考來源&#xff1a; 在線書籍-linux就該這么學-第12章 安裝軟件包 配置文件/etc/samba/smb.conf 運維對待配置文件的態度&#xff0c;非必要不增加 安裝完畢后打開Samba服務程序的主配置文件&#xff0c;好在參數并不多&#xff0c;只有37行。其中第17&#xff5e;22行代…

常用設計模式系列(十三)—組合模式

常用設計模式系列&#xff08;十三&#xff09;—組合模式 第一節 前言 hello大家好&#xff0c;今年已經過去了一半&#xff0c;年初立下的flag&#xff0c;不知道實現了沒有&#xff0c;你的flag改了多少次&#xff1f;無論自己的愿望是否完成&#xff0c;我們都應該懷揣著追…

字節碼操作工具——ByteBuddy應用(3)安全檢查

一、檢測方法名是否符合規范1、代碼&#xff08;1&#xff09;MethodLoggerAgentpackage com.example.agent;import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.asm.Advice; import net.bytebuddy.matcher.ElementMatchers;import java.lang.instrument.…

NineData 數據庫 DevOps 全面支持 GaussDB,國產化管理再升級!

NineData 數據庫 DevOps 平臺現已全面兼容 GaussDB 全線產品&#xff08;包括 GaussDB 企業級、DWS 數據倉庫、openGauss 開源版&#xff09;&#xff0c;實現一站式管理。無論 GaussDB 實例部署在哪個環境&#xff0c;企業所有開發者都可以通過 NineData 統一訪問&#xff0c;…

C++ - 模板進階

一、非類型模板參數模板參數 分為 類型形參與 非類型形參。 類型形參&#xff1a;出現在模板參數列表中&#xff0c;跟在 class 或者 typename 之類的參數類型名稱。 非類型形參&#xff0c;就是用一個常量作為類(函數)模板的一個參數&#xff0c;在類(函數)模板中可將該參數…

【質量管理】軟件缺陷管理實施方案(專業版)

引言 方案目標與范圍 本方案以CMMI量化管理要求與ISO 9000質量體系為框架,核心目標是通過標準化缺陷管理流程實現缺陷全生命周期可控。具體包括:確保軟件缺陷在全生命周期中被及時發現與修復,減少其對軟件質量、發布計劃及用戶體驗的負面影響;以“零缺陷”為首要目標,針對…

Elasticsearch 講解及 Java 應用實戰:從入門到落地

在數據量爆炸的今天&#xff0c;傳統數據庫的查詢能力越來越難以滿足復雜的檢索需求。比如電商平臺的商品搜索&#xff0c;需要支持關鍵詞模糊匹配、多條件篩選、熱門度排序等功能&#xff0c;這時候 Elasticsearch&#xff08;簡稱 ES&#xff09;就成了最佳選擇。作為一款分布…

docker pull weaviate 國內拉取失敗的問題

我是校內網&#xff0c;嘗試了 改鏡像源 (cooragent) ruiyCJQ:~/sdb/B/cooragent$ sudo vim /etc/docker/daemon.json [sudo] password for ruiy: (cooragent) ruiyCJQ:~/sdb/B/cooragent$ sudo service docker restart (cooragent) ruiyCJQ:~/sdb/B/cooragent$ sudo docke…

Vue項目使用Univer Sheets

Univer Excel主頁鏈接&#xff1a;安裝步驟 1. 安裝 使用預設模式的包管理器安裝 - 預設模式&#xff1a;可以理解為開包即用的模式&#xff0c;省去很多配置&#xff0c;當然自由度不如插件模式 pnpm add univerjs/presets univerjs/preset-sheets-core2. 前端代碼 <te…

Python day24

浙大疏錦行 python day24 內容&#xff1a; 元組&#xff1a;類比于列表&#xff0c;不過元組的元素不能被修改&#xff0c;顯示也是從[]改為了()&#xff0c;其余操作則是和列表類似&#xff0c;且元組是有序的可迭代對象&#xff1a;即可以使用迭代器訪問的對象&#xff0c…

Three.js 動畫系統入門:Tween.js 與 AnimationMixer 的使用

引言 動畫是 Three.js 中增強 3D 場景動態效果的核心技術&#xff0c;能夠為用戶帶來沉浸式體驗。Three.js 支持通過 Tween.js 實現簡單的屬性動畫&#xff0c;以及通過 AnimationMixer 處理復雜的混合動畫和骨骼動畫。本文將深入探討如何使用 Tween.js 控制 Object3D 的屬性動…

裝修進度管理系統功能對比:主流工具9選

本文分享了9款常用的裝修進度管理軟件&#xff0c;包括&#xff1a;1.Worktile&#xff1b;2.中望軟件&#xff1b;3.三維家&#xff1b;4.Procore&#xff1b;5.易達裝修管理系統&#xff1b;6.裝修管家&#xff1b;7.Zoho Projects&#xff1b;8.中建君聯&#xff1b;9.一品裝…

深度學習篇---預訓練模型

在深度學習中&#xff0c;預訓練模型&#xff08;Pretrained Model&#xff09; 是提升開發效率和模型性能的 “利器”。無論是圖像識別、自然語言處理還是語音識別&#xff0c;預訓練模型都被廣泛使用。下面從概念、使用原因、場景、作用等方面詳細介紹&#xff0c;并結合 Pyt…

Redis ①⑦-分布式鎖

分布式鎖 分布式鎖是鎖的一種&#xff0c;都是為了解決多線程/多進程環境下&#xff0c;對共享資源的訪問沖突問題。 不過&#xff0c;像 Java 的 synchronized 或者 C 的 mutex 這種鎖&#xff0c;都是進程內的鎖&#xff0c;而分布式鎖則是跨越進程/機器的鎖。也就是可以針對…

OpenCV-圖像預處理?【圖像顏色空間轉換、灰度化實驗、二值化處理、鏡像翻轉 和 仿射變換】

文章目錄先言一、圖像顏色空間轉換1.RGB顏色空間2.顏色加法3.顏色加權加法4.HSV顏色空間5.圖像轉換&#xff08;cvtColor()&#xff09;二、灰度實驗1.灰度圖2.圖像灰度化&#xff08;最大值法&#xff09;3.圖像灰度化&#xff08;平均值法&#xff09;4.圖像灰度化&#xff0…

APP逆向 day9 安卓開發基礎

一.前言 app逆向當然要學安卓基礎啦&#xff01;今天我們來教安卓基礎當然&#xff0c;安卓基礎不會教的很多&#xff0c;比java還要少&#xff0c;還是那句話&#xff0c;了解就好。 二.安卓環境搭建 2.1 安卓介紹 如果做安卓開發 需要會java代碼安卓SDK(安卓提供的內置…