模擬實現STL中的list容器

list

  • 前言
    • 一、list的節點結構設計
    • 二、迭代器設計
    • 三、list類的實現
      • 3.1 類的成員變量和類型定義
      • 3.2 構造函數與析構函數
      • 3.3 元素訪問與迭代器接口
      • 3.4 插入與刪除操作
      • 3.5 其他常用操作
    • 四、總結
  • 每文推薦


前言

在C++ STL中,list是一個非常常用的容器,它基于雙向循環鏈表實現,具有高效的插入和刪除操作。本文將詳細介紹如何模擬實現一個簡易版的STL list容器,包括節點結構、迭代器設計以及list類的核心功能實現。


一、list的節點結構設計

list的底層是雙向循環鏈表,因此首先需要設計鏈表的節點結構。每個節點應包含數據域和兩個指針域(前驅和后繼):

template<class T>
struct ListNode
{typedef ListNode<T> Node;ListNode(const T& val = T());~ListNode();Node* _next;  // 指向后繼節點Node* _prev;  // 指向前驅節點T _val;       // 節點存儲的數據
};template<class T>
ListNode<T>::ListNode(const T& val):_next(nullptr), _prev(nullptr), _val(val)
{}template<class T>
ListNode<T>::~ListNode()
{_next = nullptr;_prev = nullptr;_val = T();
}

二、迭代器設計

list的迭代器與vector不同,它不能是簡單的指針,因為list的節點在內存中不是連續存儲的。我們需要設計一個迭代器類,通過重載運算符來模擬指針的行為。

template<class T, class value_type>
struct ListIterator
{typedef ListNode<T> Node;Node* _node;  // 指向當前節點ListIterator(Node* node = nullptr);// 重載各種運算符ListIterator<T, value_type>& operator=(const ListIterator<T, value_type>& it);ListIterator<T, value_type>& operator++();       // 前置++ListIterator<T, value_type> operator++(int);     // 后置++ListIterator<T, value_type>& operator--();       // 前置--ListIterator<T, value_type> operator--(int);     // 后置--value_type& operator*();                         // 解引用value_type* operator->();                        // 箭頭運算符bool operator==(const ListIterator<T, value_type>& it);bool operator!=(const ListIterator<T, value_type>& it);
};

迭代器的核心運算符實現:

// 前置++
template<class T, class value_type>
ListIterator<T, value_type>& ListIterator<T, value_type>::operator++()
{_node = _node->_next;return *this;
}// 后置++
template<class T, class value_type>
ListIterator<T, value_type> ListIterator<T, value_type>::operator++(int)
{ListIterator<T, value_type> tmp = *this;_node = _node->_next;return tmp;
}// 解引用運算符
template<class T, class value_type>
value_type& ListIterator<T, value_type>::operator*()
{return _node->_val;
}// 箭頭運算符
template<class T, class value_type>
value_type* ListIterator<T, value_type>::operator->()
{return &(_node->_val);
}

三、list類的實現

list類需要維護一個雙向循環鏈表,我們使用一個頭節點(哨兵節點)來簡化邊界條件的處理。


3.1 類的成員變量和類型定義

template<class T>
class list
{
public:typedef ListNode<T> Node;// 定義迭代器類型,普通迭代器和const迭代器typedef ListIterator<T, T> iterator;typedef ListIterator<T, const T> const_iterator;// ... 成員函數聲明
private:Node* _head;  // 頭節點(哨兵節點)
};

3.2 構造函數與析構函數

// 默認構造函數
template<class T>
list<T>::list()
{_head = new Node;_head->_next = _head;  // 循環指向自身_head->_prev = _head;
}// 范圍構造函數
template<class T>
template <class InputIterator>
list<T>::list(InputIterator first, InputIterator last)
{_head = new Node;_head->_next = _head;_head->_prev = _head;while (first != last){push_back(*first);first++;}
}// 析構函數
template<class T>
list<T>::~list()
{Node* cur = _head->_next;while (cur != _head){Node* next = cur->_next;delete cur;cur = next;}delete _head;_head = nullptr;
}

3.3 元素訪問與迭代器接口

// 迭代器接口
template<class T>
typename list<T>::iterator list<T>::begin()
{return iterator(_head->_next);  // 第一個元素是頭節點的下一個
}template<class T>
typename list<T>::iterator list<T>::end()
{return iterator(_head);  // 尾后迭代器指向頭節點
}// 元素訪問
template<class T>
T& list<T>::front()
{assert(!empty());return _head->_next->_val;  // 第一個元素
}template<class T>
T& list<T>::back()
{assert(!empty());return _head->_prev->_val;  // 最后一個元素
}

3.4 插入與刪除操作

list的插入和刪除操作是其核心優勢,時間復雜度為O(1):

// 頭插
template<class T>
void list<T>::push_front(const T& val)
{Node* new_node = new Node(val);// 插入到頭節點和第一個元素之間new_node->_prev = _head;new_node->_next = _head->_next;_head->_next->_prev = new_node;_head->_next = new_node;
}// 尾插
template<class T>
void list<T>::push_back(const T& val)
{Node* new_node = new Node(val);// 插入到最后一個元素和頭節點之間new_node->_prev = _head->_prev;new_node->_next = _head;_head->_prev->_next = new_node;_head->_prev = new_node;
}// 指定位置插入
template<class T>
typename list<T>::iterator list<T>::insert(iterator position, const T& val)
{Node* new_node = new Node(val);// 插入到position之前new_node->_prev = position._node->_prev;new_node->_next = position._node;position._node->_prev->_next = new_node;position._node->_prev = new_node;return iterator(new_node);  // 返回指向新節點的迭代器
}// 指定位置刪除
template<class T>
typename list<T>::iterator list<T>::erase(iterator position)
{// 調整前后節點的指針關系position._node->_prev->_next = position._node->_next;position._node->_next->_prev = position._node->_prev;iterator ret = position._node->_next;  // 記錄下一個位置delete position._node;  // 釋放節點內存return ret;  // 返回下一個位置的迭代器
}

3.5 其他常用操作

// 清空鏈表
template<class T>
void list<T>::clear()
{Node* cur = _head->_next;while (cur != _head){Node* next = cur->_next;delete cur;cur = next;}// 恢復頭節點的循環指向_head->_prev = _head;_head->_next = _head;
}// 反轉鏈表
template<class T>
void list<T>::reverse()
{Node* cur = _head->_next;while (cur != _head){Node* tmp = cur->_next;std::swap(cur->_prev, cur->_next);  // 交換前后指針cur = tmp;}// 交換頭節點的前后指針std::swap(_head->_prev, _head->_next);
}// 移除所有值為val的元素
template<class T>
void list<T>::remove(const T& val)
{iterator cur = begin();while (cur != end()){if (*cur == val){cur = erase(cur);  // 刪除后自動移動到下一個元素}else{++cur;}}
}

四、總結

本文實現了一個簡易版的STL list容器,包含了list的核心功能:

  1. 基于雙向循環鏈表,使用哨兵節點簡化邊界處理
  2. 實現了功能完善的迭代器,支持++、–、*、->等操作
  3. 提供了插入、刪除、反轉、移除等常用操作

與vector相比,list的優勢在于插入和刪除操作的高效性(O(1)時間復雜度),但隨機訪問性能較差(O(n)時間復雜度)。在實際開發中,應根據具體需求選擇合適的容器。

完整代碼實現了更多細節,如拷貝構造、賦值運算、區間插入、splice操作等,感興趣的讀者可以參考代碼進行深入學習。

如需源碼,可在我的gitee上找到,下面是鏈接:
list
如對您有所幫助,可以來個三連,感謝大家的支持。


每文推薦

陳粒–小半
范瑋琪、張韶涵–如果的事
孫燕姿–克卜勒

學技術學累了時可以聽歌放松一下。


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

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

相關文章

Debug-039-el-date-picker組件手動輸入時間日期的問題處理

圖1-外輸入框圖2-內輸入框圖3問題描述&#xff1a;這兩天在迭代功能的時候&#xff0c;基本上碰到的問題都是出自這個“時間日期選擇框”&#xff0c;昨天的bug38也是解決這個組件。如上圖1和2所示&#xff0c;可以把圖1中的輸入框叫外輸入框&#xff0c;圖2中的輸入框叫內輸入…

docker-runc not installed on system

問題 Docker build時Dockerfile有RUN命令執行報錯shim error: docker-runc not installed on system&#xff0c;如下&#xff1a;解決方法 修改/etc/docker/daemon.json&#xff0c;添加正面內容 {"runtimes": {"docker-runc": {"path": "…

【秋招筆試】2025.08.27華為秋招研發崗真題

?? 點擊直達筆試專欄 ??《大廠筆試突圍》 ?? 春秋招筆試突圍在線OJ ?? 筆試突圍在線刷題 bishipass.com 題目一:智能溫控系統監測 1??:使用滑動窗口技術維護有效溫度區間 2??:利用單調隊列高效維護窗口內的最大值和最小值 3??:動態調整窗口邊界,確保滿足溫…

Kafka 消費模型

文章目錄1. 一個消費者組中只有 1 個消費者2. 一個消費者組中有 2 個消費者3. 消費者數量 > 分區數量4. 多個消費者讀取同一個分區5. 消費者放入消費者組5.1 何時放入同一個消費者組5.2 何時放入不同的消費者組1. 一個消費者組中只有 1 個消費者 假設我們有一個 TopicT1&am…

【路由器】TP Link 路由器為何無法進入管理后臺

TL-WR710N是TP Link在很多年前發布的一個迷你型的便攜路由器&#xff0c;一插上還能用&#xff0c;直接reset打算重設密碼&#xff0c;結果根據它給的192.168.1.253根本打不開。# 解決方法ping一下192.168.1.253&#xff0c;無法連接。這個問題本質上是 你電腦/手機的 IP 和路由…

LightGBM(Light Gradient Boosting Machine,輕量級梯度提升機)梳理總結

LGB微軟團隊在 2017 年提出的梯度提升樹模型&#xff0c;核心定位是 “更高效的 XGBoost”—— 它在保持精度接近 XGBoost 的同時&#xff0c;通過“數據采樣優化”“特征壓縮”“樹生長策略改進”三大創新&#xff0c;將訓練速度提升 10-100 倍&#xff0c;內存消耗降低數倍&a…

畢業項目推薦:29-基于yolov8/yolov5/yolo11的光伏板檢測識別系統(Python+卷積神經網絡)

文章目錄 項目介紹大全&#xff08;可點擊查看&#xff0c;不定時更新中&#xff09;概要一、整體資源介紹技術要點功能展示&#xff1a;功能1 支持單張圖片識別功能2 支持遍歷文件夾識別功能3 支持識別視頻文件功能4 支持攝像頭識別功能5 支持結果文件導出&#xff08;xls格式…

【實時Linux實戰系列】實時數據可視化技術實現

在當今數據驅動的世界中&#xff0c;實時數據可視化已成為理解和利用實時信息的關鍵工具。無論是在金融交易監控、工業生產監控、智能交通管理還是物聯網設備監控中&#xff0c;能夠將復雜的數據以直觀的圖表形式展示出來&#xff0c;對于快速決策和問題解決至關重要。實時數據…

【LeetCode每日一題】21. 合并兩個有序鏈表 2. 兩數相加

每日一題21. 合并兩個有序鏈表題目總體思路算法步驟時間復雜度與空間復雜度代碼2. 兩數相加題目總體思路算法步驟時間復雜度與空間復雜度代碼知識感悟2025.8.3021. 合并兩個有序鏈表 題目 將兩個升序鏈表合并為一個新的 升序 鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所…

DVWA靶場通關筆記-文件包含(Impossible級別)

目錄 一、源碼分析 二、文件包含防范分析 1、明確指定允許包含的文件 2、拒絕所有未在白名單中的輸入 3、總結 &#xff08;1&#xff09;白名單 (Allow List) &#xff08;2&#xff09;硬編碼/映射 (Hardcoding/Mapping) &#xff08;3&#xff09;輸入過濾 (Input F…

構建堅不可摧的數據堡壘:深入解析 Oracle 高可用與容災技術體系

在當今數字化時代&#xff0c;數據是企業的核心資產&#xff0c;而承載這些數據的數據庫系統的連續性與穩定性直接關系到企業的生死存亡。一次計劃外的停機或災難性的數據丟失&#xff0c;帶來的不僅是經濟上的巨大損失&#xff0c;更是對品牌信譽和客戶信任的致命打擊。因此&a…

【3D算法技術入門】如何基于建筑圖片重建三維數字資產?

要基于建筑圖片重建三維數字資產是一個復雜的計算機視覺任務&#xff0c;涉及圖像采集、特征提取、相機姿態估計、稠密重建和三維模型優化等多個步驟。下面我將提供一個基于Python的解決方案框架&#xff0c;使用開源庫實現從圖片到三維模型的基本流程。 首先需要安裝必要的庫&…

?CVPR2025 自動駕駛半監督 LiDAR 分割新范式:HiLoTs 框架深度解析

&#x1f4c4;論文題目&#xff1a;HiLoTs: High-Low Temporal Sensitive Representation Learning for Semi-Supervised LiDAR Segmentation in Autonomous Driving ??作者及機構&#xff1a; R.D. Lin、Pengcheng Weng、Yinqiao Wang、Fei Wang&#xff08;西安交通大學軟件…

【 MYSQL | 基礎篇 函數與約束 】

摘要&#xff1a;本文介紹數據庫中的函數與約束&#xff0c;函數含字符串、數值、日期、流程四類&#xff0c;可實現字符串處理、數值計算等需求。約束分六類&#xff0c;重點講外鍵約束的語法、刪除更新行為&#xff0c;保證數據正確完整。思維導圖1. 函數函數是指一段可以直接…

Oracle 數據庫性能調優:從瓶頸診斷到精準優化之道

引言&#xff1a;性能優化的本質在當今數據驅動的時代&#xff0c;數據庫性能直接關系到企業的運營效率和用戶體驗。Oracle 作為全球領先的關系型數據庫管理系統&#xff0c;承載著眾多企業的核心業務。然而&#xff0c;隨著數據量的增長和業務復雜度的提升&#xff0c;數據庫性…

楊校老師競賽課堂之C++語言GESP一級筆記

考試大綱 GESP一級考試大綱 計算機基礎與編程環境 計算機歷史 變量的定義與使用 基本數據類型&#xff08;整型、浮點型、字符型、布爾型&#xff09; 輸入與輸出&#xff08;cin與cout、scanf與printf&#xff09; 基本運算&#xff08;算術運算、關系運算、邏輯運算&am…

操作系統-管程

1. 為什么需要管程&#xff1f;—— 信號量 (Semaphore) 的困境在理解管程之前&#xff0c;你必須先知道它要解決什么問題。之前&#xff0c;我們使用信號量 (Semaphore) 來實現進程/線程間的同步與互斥。雖然信號量功能強大&#xff0c;但它存在兩個主要問題&#xff1a;編程復…

日志的實現

目錄 日志與策略模式 Log.hpp class LogStrategy基類 class ConsoleLogStrategy派生類 classFileLogStrategy派生類 日志等級 獲得時間戳 localtime_r函數詳解 函數原型 struct tm結構的指針 Logger類(重點) class LogMessage 日志信息類 std::stringstream 用法 重…

【論文閱讀】Sparse4D v2:Recurrent Temporal Fusion with Sparse Model

標題&#xff1a; Sparse4D v2&#xff1a;Recurrent Temporal Fusion with Sparse Model 作者&#xff1a; Xuewu Lin, Tianwei Lin, Zixiang Pei, Lichao Huang, Zhizhong Su motivation 在v1的基礎上&#xff0c;作者發現長時序有更好的效果&#xff0c;但v1的計算量太大&am…

構建免費的音視頻轉文字工具:支持多語言的語音識別項目

在當今數字時代&#xff0c;音視頻內容越來越多&#xff0c;但如何快速將其轉換為文字一直是一個挑戰。本項目提供了一個免費的解決方案&#xff0c;支持將視頻和音頻文件轉換為文字&#xff0c;并且支持多語言識別。 一個支持中英文的音視頻轉文字工具&#xff0c;集成了 Vos…