c++編程14——STL(3)list

歡迎來到博主的專欄:c++編程
博主ID:代碼小豪


文章目錄

    • list
      • 成員類型
      • 構造、析構、與賦值
      • iterator
      • 元素訪問
      • 修改元素
      • list的操作

list

list的數據結構是一個鏈表,準確的說應該是一個雙向鏈表。這是一個雙向鏈表的節點結構:
在這里插入圖片描述
list的使用方式和vector大差不差,區別主要還是體現在某些操作的效率方面,如下:

listvector
插入與刪除O(1)O(N)
遍歷O(N)O(N)
訪問O(N)O(1)

總體而言,如果線性表需要大量的刪除和插入,那么使用list會更加高效,如果只是單純的存儲數據,vector比list更好用,而且vector的空間還比list小。

OK,話不多說,開始看看list都有什么操作。

成員類型

由于STL中的容器都是模板類,因此數據的類型和常見的內置類型肯定不同,了解成員類型可以更好的讀懂list的各個函數原型。

list的模板如下:

template < class T, class Alloc = allocator<T> > 
class list;

函數原型常見類型有:

類型作用
value_type模板當中的第一個類型,即T
referencevalue_type類型的引用,即T&
pointervalue_type類型的指針,即T*
size_type代表無符號整型
difference_type代表有符號整型

希望大家能記住以上類型,因為接下來的list的函數原型經常會出現上述類型的參數。

構造、析構、與賦值

由于博主也不太會使allocator,因此介紹使用list的時候,參數一律使用alloc的缺省值。

default (1)	
explicit list (const allocator_type& alloc = allocator_type());
fill (2)	
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);
  1. default構造:初始化時不傳入任何參數,就能實例化出一個空鏈表。
	list<int> L1;//實例化一個容納int變量的空鏈表list<float> L2;//實例化一個容納int變量的空鏈表list<string>L3;//實例化一個容納string對象的空鏈表
  1. 填充(fill)構造:構造一個n個值為val的對象的鏈表。
	list<int>L4(4, 2);//{2,2,2,2}list<float>L5(5, 3.14);//{ 3.14, 3.14, 3.14, 3.14, 3.14}list<string>L6(2, "hello world");//{"hello world","hello world"}
  1. c++11標準還支持使用initializer_list初始化。
list (initializer_list<value_type> il,const allocator_type& alloc = allocator_type());

這種初始化方式非常方便,非常好用。關于initializer_list的介紹可以去看看博主的c++雜談系列。

使用方法大致如下:

	list<int>L7{ 1,2,3,4,5 };//{1,2,3,4,5}list<string>L8{ "haha","hehe","xixi"};//{"haha","hehe","xixi"}

是不是有點像給數組初始化時的用法,非常方便。

  1. 范圍(range)構造

這種該構造是通過使用傳入迭代器的方式,將迭代器內的元素傳入list容器當中。

list<int>L7{ 1,2,3,4,5 };//{1,2,3,4,5}
list<string>L8{ "haha","hehe","xixi"};//{"haha","hehe","xixi"}
list<int>L9(L7.begin(), L7.end());//{1,2,3,4,5}
list<string>L9(L8.begin(), L8.end());//{"haha","hehe","xixi"}

當然了,這里的迭代器可以是與list<T>相同類型的迭代器。比如這種用法也是合理的。

	string str("hello world");list<char>L11(str.begin(), str.end());//{'h','e','l','l','o',' ','w','o','r','d'}

當然了,上面的說法是存在嚴重錯誤的,list<char>和string::iterator的類型當然是不一樣的,只是讀起來順口而已。實際上我想表達的是:list<char>容器的元素類型是char,而string::iterator指向的元素也是char類型。因此可以這樣構造。

  1. 拷貝(copy)構造,構造一個與x一致的容器。
list<int>L12{ 1,2,3,4,5 };
list<int>L13(L12);//L13與L12一致

賦值運算符重載和拷貝構造的使用方法完全一致

 list& operator= (const list& x);
	list<int> list1{ 1,2,3,4 };list<int>list2;list2 = list1;//list2與list1一致

至于析構函數則沒什么需要大家操作的地方了,當list超出作用域時,會自動調用list的析構函數。而且list析構函數還不需要傳入參數

iterator

list的迭代器也是分為四種,分別是

(1)正向迭代器
(2)正向定值迭代器
(3)反向迭代器
(4)反向定值迭代器

STL的迭代器用法基本差不多,這里博主就不多演示怎么使用了,大家可以參考vector和string的迭代器用法。

list迭代器的不同之處在于,vector和string的迭代器都是隨機迭代器(random access iterator),而list是雙向迭代器(bidirectional iterator),隨機迭代器可以支持++,–,以及加減算術的操作,而雙向迭代器只能使用++或者–操作。

list<int>list1{ 1,2,3,4,5,6 };
list<int>::iterator it = list1.begin();
it + 1;//error,雙向迭代器不支持算術加減
it++;//ok,雙向迭代器支持自加自減

這意味著我們可以通過一下兩種方式遍歷list1.

list<int>list1{ 1,2,3,4,5,6 };
list<int>::iterator it = list1.begin();while (it != list1.end())
{cout << *it;it++;
}for (auto& e : list1)
{cout << e;
}

元素訪問

list不支持使用下標訪問符([])訪問容器內的元素了。實際上,list一共就提供了兩個函數,一個front,一個back。用來訪問第一個或者最后一個元素。

reference front();
const_reference front() const;
reference back();
const_reference back() const;
list1.front() = 7;//第一個元素1修改成7
list1.back() = 1;//最后一個元素修改成1

修改元素

大家看看list關于修改元素的函數結口,是不是感覺很熟悉
在這里插入圖片描述
可以發現list和vector關于修改元素的函數接口簡直是如出一轍、

這是因為Victor,string,list都是線性表的結構,因此對元素的修改操作的效果都是一致的,區別只在于涉及的算法不同,這里我打算將算法放在list的模擬實現當中講解,或者也可以去看博主的C語言數據結構關于雙鏈表的博客。

list的操作

list和vector雖然在邏輯上是一致的,但是在內存結構上卻完全不同了,因此list可執行的操作和vector是不同的。

在這里插入圖片描述

  1. remove——移除所有值為val的節點
void remove (const value_type& val);
  1. unique——去掉鏈表中所有的重復元素。(鏈表需有序)
	list<int>list2{ 5,6,3,2,1,1,5 };list2.sort();//排序list2.unique();//list2={1,2,3,5,6}
  1. sort——排序
(1)	void sort();
(2)	
template <class Compare>void sort (Compare comp);

默認情況下會將鏈表排成升序,如果想要將鏈表排成降序,就需要用到仿函數(像函數一樣使用的類)。

	list<int>list2{ 5,6,3,2,1,1,5 };list2.sort();//升序for (auto& e : list2){cout << e << ' ';}cout << endl;list2.sort(greater<int>());//降序,這個greater是一個仿函數模板,博主不做說明for (auto& e : list2){cout << e << ' ';}
  1. reverse——逆置鏈表
void reverse();

reverse可以讓鏈表中的所有元素的順序顛倒過來。

  1. merge——合并鏈表
(1)	void merge (list& x);
(2)	
template <class Compare>void merge (list& x, Compare comp);

(1)
list容器將與x合并,merge會將x的所有成員都轉移到list容器當中。(x會變成一個空鏈表,而list則會變大)。合并的兩個鏈表必須擁有相同的順序(升序,不能是逆序)。合并后的鏈表也會呈升序

list<int>list4{6,5,5,3,5};list<int>list5{ 7,9,3,4,2 };list4.sort();//list4排成升序list5.sort();//list5排成升序list4.merge(list5);//將list5和list4合并for (auto& e : list4){cout << e << ' ';//{2,3,3,4,5,5,5,6,7,9}}

(2)
如果我們想要讓合并后的鏈表是逆序的,那就將待合并的鏈表排成逆序,再傳入仿函數comp,可以讓合并后的鏈表呈逆序。

list<int>list4{6,5,5,3,5};list<int>list5{ 7,9,3,4,2 };list4.sort(greater<int>());//排成逆序list5.sort(greater<int>());//排成逆序list4.merge(list5,greater<int>());//合并成逆序for (auto& e : list4){cout << e << ' ';//{9,7,6,5,5,5,4,3,3,2}}
  1. splice——粘接(感覺像是剪切)
entire list (1)	
void splice (iterator position, list& x);
single element (2)	
void splice (iterator position, list& x, iterator i);
element range (3)	
void splice (iterator position, list& x, iterator first, iterator last);

splice重載了三個版本,每個版本都有不一樣的效果

第一版:全部粘接,將x的全部元素粘接到list容器的迭代器指向的位置。x會變成一個空鏈表。

	list<int>list1{ 1,2,3,4 };list<int>list2{ 10,20,30,40 };list1.splice(list1.begin(), list2);for (auto& e : list1){cout << e << ' '; //{10, 20, 30, 40, 1, 2, 3, 4};}

第二版,單元素粘接,將x中的迭代器i指向的元素粘接到容器position指向的位置。

	list<int>list1{ 1,2,3,4 };list<int>list2{ 10,20,30,40 };list1.splice(list1.begin(), list2,list2.begin());for (auto& e : list1){cout << e << ' '; //{10,1, 2, 3, 4};}

第三版,迭代區間粘接。將x中[first,last)區間內的所有元素都粘接到list容器的position位置上。

	list<int>list1{ 1,2,3,4 };list<int>list2{ 10,20,30,40 };list1.splice(++list1.begin(), list2,++list2.begin(),--list2.end());for (auto& e : list1){cout << e << ' '; //{1,20,30 2, 3, 4};}

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

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

相關文章

Vue學習筆記3——事件處理

事件處理 1、事件處理器&#xff08;1&#xff09;內聯事件處理器&#xff08;2&#xff09;方法事件處理器 2、事件參數3、事件修飾符 1、事件處理器 我們可以使用v-on 指令(簡寫為)來監聽DOM事件&#xff0c;并在事件觸發時執行對應的JavaScript。 用法: v-on:click"me…

JVM學習-執行引擎

執行引擎 執行引擎是Java虛擬機核心組成部分之一虛擬機是一個相對于物理機的概念&#xff0c;這兩種機器都有代碼執行能力&#xff0c;其區別是物理機的執行引擎是直接建立在處理器、緩存、指令集和操作系統層面上的&#xff0c;而虛擬機的執行引擎是由軟件自行實現的&#xf…

【算法】遞歸、搜索與回溯——簡介

簡介&#xff1a;遞歸、搜索與回溯&#xff0c;本節博客主要是簡單記錄一下關于“遞歸、搜索與回溯”的相關簡單概念&#xff0c;為后續算法做鋪墊。 目錄 1.遞歸1.1遞歸概念2.2遞歸意義2.3學習遞歸2.4寫遞歸代碼步驟 2.搜索3.回溯與剪枝 遞歸、搜索、回溯的關系&#xff1a; …

ICML2024 定義新隱私保護升級:DP-BITFIT新型微調技術讓AI模型學習更安全

DeepVisionary 每日深度學習前沿科技推送&頂會論文分享&#xff0c;與你一起了解前沿深度學習信息&#xff01; 引言&#xff1a;差分隱私在大模型微調中的重要性和挑戰 在當今的深度學習領域&#xff0c;大型預訓練模型的微調已成為提高各種任務性能的關鍵技術。然而&am…

推特熱帖:大語言模型自薦能夠替代的20種人類工作!快來看你是否需要轉行!

最近推特上有一個例子引起了廣泛的討論&#xff0c;事情的起因是這樣的&#xff1a;網友讓 GPT-4o 預測一下自己未來將會替代人類哪些工作&#xff1f; 這聽起來很有趣&#xff01;GPT-4o會給出什么樣的預測呢&#xff1f; 3.5研究測試&#xff1a;hujiaoai.cn 4研究測試&…

02-Linux【基礎篇】

一、Linux的目錄結構 1.基本介紹 Linux的文件系統采用層級式的樹狀目錄結構&#xff0c;在此結構中的最上層是根目錄"/"&#xff0c;然后在此目錄下再創建其他的目錄 深刻理解Linux樹狀文件目錄是非常重要的 記住一句經典的話&#xff1a;在Linux世界里&#xff…

如何在 DigitalOcean Droplet 云主機上創建 Ubuntu 服務器

在本文中&#xff0c;你將通過 DigitalOcean 的管理面板創建一個 Ubuntu 服務器&#xff0c;并將其配置為使用你的 SSH 密鑰。設置好服務器后&#xff0c;你可以在其上部署應用程序和網站。 本教程是DigitalOcean云課程簡介的一部分&#xff0c;它指導用戶完成將應用程序安全地…

win10右鍵沒有默認打開方式的選項的處理方法

問題描述 搞了幾個PDF書籍學習一下&#xff0c;不過我不想用默認的WPS打開&#xff0c;因為WPS太惡心人了&#xff0c;占用資源又高。我下載了個Sumatra PDF&#xff0c;這時候我像更改pdf文件默認的打開程序&#xff0c;發現右擊沒有這個選項。 問題解決 右擊文件–屬性–…

汽車以太網發展現狀及挑戰

一、汽車以太網技術聯盟 目前推動汽車以太網技術應用與發展的組織包括&#xff1a;OPEN Alliance&#xff08;One-Pair Ether-Net Alliance SIG&#xff09;聯盟&#xff0c;主要致力于汽車以太網推廣與使用&#xff0c;該聯盟通過推進 BroadR- Reach 單對非屏蔽雙絞線以太網傳…

設計新境界:大數據賦能UI的創新美學

設計新境界&#xff1a;大數據賦能UI的創新美學 引言 隨著大數據技術的蓬勃發展&#xff0c;它已成為推動UI設計創新的重要力量。大數據不僅為界面設計提供了豐富的數據資源&#xff0c;還賦予了設計師以全新的視角和工具來探索美學的新境界。本文將探討大數據如何賦能UI設計…

面試八股之JVM篇3.5——垃圾回收——G1垃圾回收器

&#x1f308;hello&#xff0c;你好鴨&#xff0c;我是Ethan&#xff0c;一名不斷學習的碼農&#xff0c;很高興你能來閱讀。 ??目前博客主要更新Java系列、項目案例、計算機必學四件套等。 &#x1f3c3;人生之義&#xff0c;在于追求&#xff0c;不在成敗&#xff0c;勤通…

1688. 比賽中的配對次數

題目&#xff1a; 給你一個整數 n &#xff0c;表示比賽中的隊伍數。比賽遵循一種獨特的賽制&#xff1a; 如果當前隊伍數是 偶數 &#xff0c;那么每支隊伍都會與另一支隊伍配對。總共進行 n / 2 場比賽&#xff0c;且產生 n / 2 支隊伍進入下一輪。 如果當前隊伍數為 奇數 …

python梯度下降法求解三元線性回歸系數,并繪制結果

import numpy as np import matplotlib.pyplot as plt # 生成隨機數據 np.random.seed(0) X1 2 * np.random.rand(100, 1) X2 3 * np.random.rand(100, 1) X3 4 * np.random.rand(100, 1) y 4 3 * X1 5 * X2 2 * X3 np.random.randn(100, 1) # 合并特征 X_b np.hsta…

Vue中組件之間的通信有哪些方法

在Vue中&#xff0c;組件之間的通信有多種方法&#xff0c;以下是一些常見的方法&#xff1a; Props和$emit&#xff1a; 父組件通過props向子組件傳遞數據。子組件通過$emit觸發事件&#xff0c;將數據傳遞給父組件。 provide和inject&#xff1a; 在Vue 2.2.0版本中引入的選…

云計算-特殊機制(Specialsed Mechanisms)

自動擴展監聽器 (Automated Scaling Listener) 自動擴展監聽器是一種特定類型的服務代理。它運行在云提供商的網絡中&#xff0c;監控云消費者和云服務之間的網絡流量。通過分析消費者和服務之間的消息量和類型&#xff0c;它可以測量云服務的負載。 自動擴展監聽器對變化的負載…

常見 JVM 面試題補充

原文地址 : 26 福利&#xff1a;常見 JVM 面試題補充 (lianglianglee.com) CMS 是老年代垃圾回收器&#xff1f; 初步印象是&#xff0c;但實際上不是。根據 CMS 的各個收集過程&#xff0c;它其實是一個涉及年輕代和老年代的綜合性垃圾回收器。在很多文章和書籍的劃分中&…

SpringCloud Alibaba的相關組件的簡介及其使用

Spring Cloud Alibaba是阿里巴巴為開發者提供的一套微服務解決方案&#xff0c;它基于Spring Cloud項目&#xff0c;提供了一系列功能強大的組件&#xff0c;包括服務注冊與發現、配置中心、熔斷與限流、消息隊列等。 本文將對Spring Cloud Alibaba的相關組件進行簡介&#xff…

React Native 之 動畫Animated(十二)

react-native 的 Animated API提供了一種聲明式的方式來創建平滑的動畫效果。它允許你編寫動畫邏輯&#xff0c;并將動畫值直接綁定到組件的樣式或布局屬性上。 react-native 的 Animated 庫通過以下方式工作&#xff1a; 創建動畫值&#xff1a;首先&#xff0c;你需要使用 A…

ROCm上運行預訓練BERT

14.10. 預訓練BERT — 動手學深度學習 2.0.0 documentation (d2l.ai) 下載數據集 在d2l-zh/pytorch/data目錄解壓&#xff1a; ~/d2l-zh/pytorch/data$ unzip wikitext-2-v1.zip Archive: wikitext-2-v1.zipcreating: wikitext-2/inflating: wikitext-2/wiki.test.tokens …

【第17章】MyBatis-Spring之注入映射器

文章目錄 前言一、注冊映射器1. XML 配置2. Java 配置 二、發現映射器1. <mybatis:scan/>2.MapperScan ( 建議 ) \color{#00FF00}{(建議)} (建議) 三、MapperScannerConfigurer總結 前言 與其在數據訪問對象&#xff08;DAO&#xff09;中手工編寫使用 SqlSessionDaoSu…