list的使用
- 一.list基本的結構
- 1.環狀雙向鏈表
- 2.哨兵節點
- 3.迭代器
- 4.節點結構
- 5.鏈表遍歷
- 6.迭代器失效
- 二.list的基本使用
- 1.`test01`函數:主要測試`std::list`的初始化方式及遍歷
- 2.`test02`函數:主要測試`std::list`的常用成員函數操作
- 3.測試結果如下
- 三.list的其他操作(了解)
- 2. remove(按值移除)
- 3. remove_if(按條件移除)
- 4. unique(移除相鄰重復)
- 5. merge(合并有序鏈表)
- 6. reverse(反轉元素順序)
一.list基本的結構
以上圖片展示了一個 C++ 標準庫中的 std::list 容器的內部結構:
1.環狀雙向鏈表
std::list
是環狀雙向鏈表。- 最后一個節點的
next
指向頭節點。 - 頭節點的
prev
指向最后一個節點。
2.哨兵節點
- 圖中紅色方框標注的是哨兵節點。
- 哨兵節點不存儲實際數據。
- 哨兵節點的
next
指向第一個數據節點。 - 哨兵節點的
prev
指向最后一個數據節點。
3.迭代器
begin()
返回指向第一個數據節點的迭代器。end()
返回指向哨兵節點的迭代器。- 迭代器通過
_M_node
指針訪問節點。
4.節點結構
- 每個節點包含數據值(如圖中 0、2、3、4 等)。
- 包含指向前一個節點的指針(
prev
)。 - 包含指向后一個節點的指針(
next
)。
5.鏈表遍歷
- 正向遍歷:從
begin()
開始,通過next
指針依次訪問節點。 - 逆向遍歷:從
end()
開始,通過prev
指針依次訪問節點。
6.迭代器失效
- 當鏈表結構改變時(如插入或刪除節點),迭代器可能失效。
- 失效的迭代器不能再用于訪問鏈表。
二.list的基本使用
對C++ 標準庫中 std::list 容器部分成員函數的測試。展示了std::list 的多種操作方式,包括初始化、插入元素、調整大小、刪除元素等。
#include<iostream>
#include<list>
#include<vector>
using namespace std;// 測試 list 的初始化和基本遍歷
void test01()
{// 默認構造函數創建空列表list<int> lt1;// 使用初始化列表構造列表list<int> lt2 = { 0,1,2,3,4,5 };// 創建包含10個元素的列表,每個元素初始化為1list<int> lt3(10, 1);// 從數組中前5個元素構造列表int a[] = { 5,4,3,2,1,0 };list<int> lt4(a, a + 5);// 正確遍歷方法:基于范圍的for循環cout << "lt4: ";for (auto e : lt4){cout << e << " ";}cout << endl;
}// 測試 list 的插入、修改和刪除操作
void test02()
{// 使用初始化列表構造并插入元素list<int> lt1 = { 0,1,2,3,4,5 };lt1.insert(lt1.begin(), 666); // 在頭部插入元素// 復制構造list<int> lt2(lt1);lt2.push_back(999); // 在尾部添加元素lt2.resize(10, 77); // 調整大小,不足部分用77填充cout << "lt2: ";for (auto e : lt2){cout << e << " ";}cout << endl;// 復制列表并調整大小(截斷)list<int> lt3 = lt2;lt3.resize(5, 0); // 調整為5個元素,超出部分截斷cout << "lt3: ";for (auto e : lt3){cout << e << " ";}cout << endl;// 刪除特定值的所有元素list<int> lt4(lt2);lt4.remove(77); // 刪除所有值為77的元素cout << "lt4: ";for (auto e : lt4){cout << e << " ";}cout << endl;
}int main() {test01();cout << endl;test02();return 0;
}
以下是對代碼中test01
和test02
函數測試內容的分要點梳理:
1.test01
函數:主要測試std::list
的初始化方式及遍歷
-
初始化測試
- 默認構造:
list<int> lt1;
(創建空列表) - 初始化列表構造:
list<int> lt2 = {0,1,2,3,4,5};
(用初始化列表直接賦值元素) - 指定大小和值構造:
list<int> lt3(10, 1);
(創建包含10個元素、每個元素值為1的列表) - 數組范圍構造:
list<int> lt4(a, a + 5);
(用數組a
中從a
到a+5
的元素初始化列表,即取前5個元素5,4,3,2,1
)
- 默認構造:
-
遍歷測試
- 使用基于范圍的for循環遍歷
lt4
并輸出元素,驗證初始化結果是否正確。
- 使用基于范圍的for循環遍歷
2.test02
函數:主要測試std::list
的常用成員函數操作
-
插入操作
lt1.insert(lt1.begin(), 666);
:在lt1
的開頭位置插入元素666
。
-
復制構造
list<int> lt2(lt1);
:通過復制構造函數,創建lt1
的副本lt2
。
-
尾部添加
lt2.push_back(999);
:在lt2
的末尾添加元素999
。
-
調整大小
lt2.resize(10, 77);
:將lt2
的大小調整為10,若原大小不足,用77
填充剩余位置。lt3.resize(5, 0);
:將lt3
的大小調整為5,若原大小超出,截斷多余元素(填充值0
在此處無效,因僅截斷不新增)。
-
刪除元素
lt4.remove(77);
:刪除lt4
中所有值為77
的元素。
-
遍歷輸出
- 所有列表均通過基于范圍的for循環遍歷輸出,驗證上述操作的結果是否正確。
3.測試結果如下
lt4: 5 4 3 2 1 lt2: 666 0 1 2 3 4 5 999 77 77
lt3: 666 0 1 2 3
lt4: 666 0 1 2 3 4 5 999
三.list的其他操作(了解)
### 1. splice(轉移元素)
- 核心功能:把一個
list
里的元素(單個、區間或整個鏈表)轉移到另一個list
里,原list
對應元素會被移除。 - 關鍵特點:
- 高效:直接調整鏈表指針,不用拷貝元素,處理大數據量時速度優勢明顯。
- “搬家式” 轉移:原
list
被轉移的元素位置會 “空出來”,目標list
把這些元素 “接過去” 。
- 典型場景:需要在不同鏈表間快速調整元素歸屬,比如鏈表拼接、拆分邏輯,像合并訂單鏈表時,把臨時鏈表的訂單直接轉移到主鏈表 。
2. remove(按值移除)
- 核心功能:遍歷鏈表,把所有值和指定值一樣的元素都刪掉。
- 關鍵特點:
- 精準定值刪除:簡單直接,給定一個具體值(如
5
),就能清理鏈表里所有該值的元素。 - 遍歷式刪除:逐個檢查元素值,匹配就刪除,適合明確知道要刪什么值的場景。
- 精準定值刪除:簡單直接,給定一個具體值(如
- 典型場景:數據清理時,刪除鏈表中特定標識的元素,比如用戶鏈表刪除 ID 為
001
的用戶記錄 。
3. remove_if(按條件移除)
- 核心功能:依據自定義條件(像元素大小、是否滿足某種規則),刪除符合條件的元素。
- 關鍵特點:
- 靈活自定義:用 lambda 表達式、函數對象等設定條件(比如刪偶數、刪大于某個閾值的數 ),應對復雜刪除需求。
- 邏輯拓展性強:不管是簡單的數值判斷,還是涉及元素對象屬性的復雜邏輯,都能實現刪除。
- 典型場景:業務規則篩選刪除,比如訂單鏈表刪除金額小于
1
元的無效訂單,學生鏈表刪除成績不及格的記錄 。
4. unique(移除相鄰重復)
- 核心功能:去掉鏈表中相鄰的重復元素,只留一個。若要整體去重,一般得先排序讓重復元素相鄰。
- 關鍵特點:
- 相鄰限定:只處理 “緊挨著” 的重復,沒排序的話,分散的重復元素刪不掉。
- 簡化存儲:適合對連續重復數據做 “壓縮”,像統計鏈表中連續相同數值的個數后,保留一個代表值 。
- 典型場景:處理傳感器連續采集的重復數據、文本處理中連續重復的字符(排序后去相鄰重復 ),比如日志鏈表清理連續重復的狀態記錄 。
5. merge(合并有序鏈表)
- 核心功能:把兩個已經有序的鏈表合并成一個新的有序鏈表,原被合并的鏈表會被清空。
- 關鍵特點:
- 前提條件:兩個鏈表自身得是有序的(升序或降序,需保持一致 ),否則合并結果會混亂。
- 歸并特性:常和歸并排序搭配,拆分后合并有序子鏈表;也用于整合多個有序鏈表結果。
- 典型場景:歸并排序算法里合并階段、合并多個按時間排序好的日志鏈表,比如服務器把不同時段有序的操作日志鏈表合并 。
6. reverse(反轉元素順序)
- 核心功能:把鏈表中元素的順序完全顛倒,第一個變最后一個,最后一個變第一個。
- 關鍵特點:
- 指針調整實現:通過修改鏈表節點間的指針指向,改變元素遍歷順序,不用額外空間拷貝。
- 邏輯簡單直接:一步操作就能實現逆序,滿足逆序處理數據需求。
- 典型場景:鏈表數據需要逆序展示(如聊天記錄從最新到最早展示時反轉 )、數學運算中鏈表存儲數字的逆序處理(像鏈表存
1->2->3
代表123
,反轉后計算321
)。
以上這些要點清晰梳理了每個函數 “能干什么、有啥特點、啥時候用”,方便理解 list
這些操作在實際場景的價值 。