C++:list模擬實現

hello,各位小伙伴,本篇文章跟大家一起學習《C++:list模擬實現》,感謝大家對我上一篇的支持,如有什么問題,還請多多指教 !
如果本篇文章對你有幫助,還請各位點點贊!!!
在這里插入圖片描述
話不多說,開始進入正題

🍁list的邏輯結構以及節點代碼

在這里插入圖片描述

是一個雙指針帶頭鏈表,所以我選擇用一個結構體ListNode來維護節點,如下:

// List的節點類
template<class T>
struct ListNode
{ListNode(const T& val = T()):_val(val),_pPre(nullptr),_pNext(nullptr){}ListNode<T>* _pPre;// 指向前一個結點ListNode<T>* _pNext;// 指向后一個節點T _val;// 該結點的值
};

我對ListNode<T>改一個名字:Node

typedef ListNode<T> Node;
typedef Node* PNode;

🍁list類

🍃私有成員變量_pHead和私有成員函數CreateHead()

private:void CreateHead()// 創建頭節點并且初始化{_pHead = new Node();_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;}PNode _pHead;

🍃尾插函數和插入函數

尾插只是插入的其中一種方式,所以實現了插入函數,就能夠實現尾插函數。
插入思路圖解:在pos位置前插入值為val的節點

創建新節點值為value后;
使prev節點的_pNext指針指向newnode,newnode的節點的_pPre指向prev;
使cur節點的_pPre指針指向newnode,newnode的節點的_pNext指向cur;
最后返回iterator(newnode);

在這里插入圖片描述

itearator為迭代器,后面會實現

  • 插入
// 在pos位置前插入值為val的節點
iterator insert(iterator pos, const T& val)
{Node* cur = pos._pNode;Node* newnode = new Node(val);Node* prev = cur->_pPre;// prev  newnode  curprev->_pNext = newnode;newnode->_pPre = prev;newnode->_pNext = cur;cur->_pPre = newnode;return iterator(newnode);
}
  • 尾插
void push_back(const T& val)
{insert(end(), val); 
}

🍃構造函數

  • 無參構造
list(const PNode& pHead = nullptr)
{CreateHead();/*_pHead = new Node();_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;*/
}
  • 帶參構造(數值)
list(int n, const T& value = T())
{CreateHead();for (int i = 0; i < n; ++i)push_back(value);
}
  • 帶參構造(迭代器)
template <class Iterator>
list(Iterator first, Iterator last)
{CreateHead();while (first != last){push_back(*first);++first;}
}
  • 拷貝構造
list(const list<T>& l)
{CreateHead();// 復用帶參構造(迭代器)list<T> temp(l.cbegin(), l.cend());// 與*this的頭節點pHead交換指向swap(temp);
}

🍃析構函數

clear()為其中的成員函數,功能:清理list中的數據

~list()
{clear();delete _pHead;_pHead = nullptr;/*Node* cur = _pHead->_pNext;Node* tmp = cur->_pNext;while (cur != _pHead){delete cur;cur = tmp;tmp = tmp->_pNext;}tmp = cur = nullptr;_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;*/
}

🍃迭代器模擬

邏輯上并不難,也許難理解于模板

//List的迭代器結構體
template<class T, class Ref, class Ptr>
struct ListIterator
{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;ListIterator(PNode pNode = nullptr):_pNode(pNode){}ListIterator(const Self& l){_pNode = l._pNode;}T& operator*(){assert(_pNode != _pNode->_pNext);return _pNode->_val;}T* operator->(){return &(*this);}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){PNode* tmp = _pNode;_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self& operator--(int){PNode* tmp = _pNode;_pNode = _pNode->_pPre;return tmp;}bool operator!=(const Self& l){return _pNode != l._pNode;}bool operator==(const Self& l){return !(*this != l);}PNode _pNode;
};

這段代碼定義了一個模板結構 ListIterator,用于表示List類的迭代器。讓我們來解釋模板聲明部分:

template<class T, class Ref, class Ptr>;

這一行是模板聲明,定義了一個模板類 ListIterator,它有三個模板參數:T、Ref 和 Ptr。讓我們逐個解釋這些參數的作用:

1.T: 這是一個模板參數,表示迭代器指向的元素類型。在使用 ListIterator 時,你需要提供實際的類型作為 T 的值。
2.Ref: 這也是一個模板參數,表示迭代器的引用類型。通常情況下,當你通過迭代器解引用(使用 * 運算符)時,你希望得到的是元素的引用類型。所以 Ref 通常被設定為 T&,表示引用類型為 T 的元素。
3.Ptr: 這是迭代器的指針類型。與 Ref 類似,當你通過迭代器解引用(使用 -> 運算符)時,你希望得到的是元素的指針類型。因此,通常情況下 Ptr 被設定為 T*,表示指針類型為 T 的元素。

通過將這些參數設定為模板參數,ListIterator 類可以適用于不同類型的元素,同時也可以提供不同的引用和指針類型。這樣做使得 ListIterator 類更加靈活,能夠適用于不同的使用場景。

  • 封裝的意義
    將迭代器的實現從 List 類中分離出來,有幾個重要的意義和優勢:
  1. 模塊化設計:通過將迭代器封裝為單獨的類,可以實現更模塊化的設計。這意味著 List 類的實現與迭代器的實現可以分開,每個類都專注于自己的職責。這樣的設計使得代碼更易于理解、維護和測試。
  2. 可重用性:通過將迭代器設計為獨立的類,可以在不同的容器類中重復使用相同的迭代器實現。例如,如果你有另一個類似于 List 的容器類,也需要迭代器來遍歷其中的元素,你可以直接重用相同的迭代器實現,而無需重新編寫。
  3. 靈活性:將迭代器設計為獨立的類使得它們的實現更加靈活。你可以在迭代器類中添加額外的功能或改變迭代器的行為,而不會影響到容器類的實現。這樣的設計使得容器和迭代器的職責分離,每個類可以獨立地演化和改進。
  4. 通用性:獨立的迭代器類可以設計成通用的,適用于多種容器類型。這意味著你可以為不同的容器類實現相同的迭代器接口,使得用戶在使用不同的容器時無需學習不同的迭代器接口,提高了代碼的一致性和可用性。

總的來說,將迭代器封裝為獨立的類使得代碼更加模塊化、可重用、靈活和通用,提高了代碼的可維護性、可擴展性和可讀性。

🍃list類中迭代器的使用

public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T&> const_iterator;
  • begin()和end()
// List Iterator
iterator begin()
{return _pHead->_pNext;
}iterator end()
{return _pHead;
}const_iterator begin() const
{return _pHead->_pNext;
}const_iterator end() const
{return _pHead;
}
  • erase
    刪除pos位置的節點,返回該節點的下一個位置
iterator erase(iterator pos)
{assert(pos._pNode != _pHead);Node* Prev = pos._pNode->_pPre;Node* Next = pos._pNode->_pNext;delete pos._pNode;Prev->_pNext = Next;Next->_pPre = Prev;return iterator(Next);
}

🍃List Modify

void push_back(const T& val) { insert(end(), val); }
void pop_back() { erase(--end()); }
void push_front(const T& val) 
{ assert(!empty());insert(begin(), val); 
}
void pop_front() { erase(begin()); }

🍁全部代碼

#pragma once
#include<assert.h>
#include<iostream>
using namespace std;namespace My_List
{// List的節點類template<class T>struct ListNode{ListNode(const T& val = T()):_val(val),_pPre(nullptr),_pNext(nullptr){}ListNode<T>* _pPre;ListNode<T>* _pNext;T _val;};//List的迭代器類template<class T, class Ref, class Ptr>struct ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;ListIterator(PNode pNode = nullptr):_pNode(pNode){}ListIterator(const Self& l){_pNode = l._pNode;}T& operator*(){assert(_pNode != _pNode->_pNext);return _pNode->_val;}T* operator->(){return &(*this);}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){PNode* tmp = _pNode;_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self& operator--(int){PNode* tmp = _pNode;_pNode = _pNode->_pPre;return tmp;}bool operator!=(const Self& l){return _pNode != l._pNode;}bool operator==(const Self& l){return !(*this != l);}PNode _pNode;};//list類template<class T>class list{typedef ListNode<T> Node;typedef Node* PNode;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T&> const_iterator;public:///// List的構造list(const PNode& pHead = nullptr){CreateHead();/*_pHead = new Node();_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;*/}list(int n, const T& value = T()){CreateHead();for (int i = 0; i < n; ++i)push_back(value);/*int cnt = 0;while (cnt < n){PNode _first = new Node(value);PNode tmp = _pHead->_pPre;tmp->_pNext = _first;_first->_pPre = tmp;_first->_pNext = _pHead;_pHead->_pPre = _first;++cnt;}*/}template <class Iterator>list(Iterator first, Iterator last){CreateHead();while (first != last){push_back(*first);++first;}/*while (first != last){PNode _first = new Node(*first);PNode tmp = _pHead->_pPre;tmp->_pNext = _first;_first->_pPre = tmp;_first->_pNext = _pHead;_pHead->_pPre = _first;++first;}*/}list(const list<T>& l){CreateHead();list<T> temp(l.cbegin(), l.cend());swap(temp);/*iterator first = l._pHead->_pNext;iterator last = l._pHead;while (first != last){PNode _first = new Node(*first);PNode tmp = _pHead->_pPre;tmp->_pNext = _first;_first->_pPre = tmp;_first->_pNext = _pHead;_pHead->_pPre = _first;++first;}*/}list<T>& operator=(const list<T> l){CreateHead();swap(l);return *this;/*iterator first = l._pHead->_pNext;iterator last = l._pHead;while (first != last){PNode _first = new Node(*first);PNode tmp = _pHead->_pPre;tmp->_pNext = _first;_first->_pPre = tmp;_first->_pNext = _pHead;_pHead->_pPre = _first;++first;}return *this;*/}~list(){clear();delete _pHead;_pHead = nullptr;/*Node* cur = _pHead->_pNext;Node* tmp = cur->_pNext;while (cur != _pHead){delete cur;cur = tmp;tmp = tmp->_pNext;}tmp = cur = nullptr;_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;*/}///// List Iteratoriterator begin(){return _pHead->_pNext;}iterator end(){return _pHead;}const_iterator begin() const{return _pHead->_pNext;}const_iterator end() const{return _pHead;}///// List Capacitysize_t size()const{Node* cur = _pHead->_pNext;size_t cnt = 0;while (cur != _pHead){++cnt;cur = cur->_pNext;}return cnt;}bool empty()const{return size() == 0;}// List AccessT& front(){return _pHead->_pNext->_val;}const T& front()const{return _pHead->_pNext->_val;}T& back(){return _pHead->_pPre->_val;}const T& back()const{return _pHead->_pPre->_val;}// List Modifyvoid push_back(const T& val) { insert(end(), val); }void pop_back() { erase(--end()); }void push_front(const T& val) { assert(!empty());insert(begin(), val); }void pop_front() { erase(begin()); }// 在pos位置前插入值為val的節點iterator insert(iterator pos, const T& val){Node* cur = pos._pNode;Node* newnode = new Node(val);Node* prev = cur->_pPre;// prev  newnode  curprev->_pNext = newnode;newnode->_pPre = prev;newnode->_pNext = cur;cur->_pPre = newnode;return iterator(newnode);}// 刪除pos位置的節點,返回該節點的下一個位置iterator erase(iterator pos){assert(pos._pNode != _pHead);Node* Prev = pos._pNode->_pPre;Node* Next = pos._pNode->_pNext;delete pos._pNode;Prev->_pNext = Next;Next->_pPre = Prev;return iterator(Next);}void clear(){iterator cur = begin();while (cur != end()){cur = erase(cur);}_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;}void swap(list<T>& l){/*list<T> tmp = l;l = *this;*this = tmp;*/PNode tmp = _pHead;_pHead = l._pHead;l._pHead = tmp;}private:void CreateHead(){_pHead = new Node();_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;}PNode _pHead;};
};

你學會了嗎?
好啦,本章對于《C++:list模擬實現》的學習就先到這里,如果有什么問題,還請指教指教,希望本篇文章能夠對你有所幫助,我們下一篇見!!!

如你喜歡,點點贊就是對我的支持,感謝感謝!!!

請添加圖片描述

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

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

相關文章

LeetCode題練習與總結:二叉樹展開為鏈表--114

一、題目描述 給你二叉樹的根結點 root &#xff0c;請你將它展開為一個單鏈表&#xff1a; 展開后的單鏈表應該同樣使用 TreeNode &#xff0c;其中 right 子指針指向鏈表中下一個結點&#xff0c;而左子指針始終為 null 。展開后的單鏈表應該與二叉樹 先序遍歷 順序相同。 …

深入探討Java字符串拼接的藝術

引言 在Java編程中&#xff0c;字符串是最基本的數據類型之一。字符串拼接是開發過程中一個非常常見的操作&#xff0c;無論是構建用戶界面的文本&#xff0c;還是生成日志信息&#xff0c;都離不開字符串的拼接。然而&#xff0c;字符串拼接的效率和正確性常常被開發者忽視&a…

格式化數據恢復指南:從備份到實戰,3個技巧一網打盡

朋友們&#xff01;你們有沒有遇到過那種“啊&#xff0c;我的文件呢&#xff1f;”的尷尬時刻&#xff1f;無論是因為手滑、電腦抽風還是其他原因&#xff0c;數據丟失都可能會讓我們抓狂&#xff0c;甚至有時候&#xff0c;我們可能一不小心就把存儲設備格式化了&#xff0c;…

香橙派OrangePI AiPro測評 【運行qt,編解碼,xfreeRDP】

實物 為AI而生 打開盒子 配置 扛把子的 作為業界首款基于昇騰深度研發的AI開發板&#xff0c;Orange Pi AIpro無論在外觀上、性能上還是技術服務支持上都非常優秀。采用昇騰AI技術路線&#xff0c;集成圖形處理器&#xff0c;擁有8GB/16GB LPDDR4X&#xff0c;可以外接32…

進程通信——管道

什么是進程通信&#xff1f; 進程通信是實現進程間傳遞數據信息的機制。要實現數據信息傳遞就要進程間共享資源——內存空間。那么是哪塊內存空間呢&#xff1f;進程間是相互獨立的&#xff0c;一個進程不可能訪問其他進程的內存空間&#xff0c;那么這塊空間只能由操作系統提…

什么是RPA自動化辦公?

RPA自動化辦公&#xff1a;提升效率的利器 如今&#xff0c;自動化辦公已成為提升效率、減少錯誤、節省成本的關鍵手段。RPA&#xff08;機器人流程自動化&#xff0c;Robotic Process Automation&#xff09;作為其中的重要組成部分&#xff0c;正受到越來越多企業的青睞。那…

【全開源】簡單商城系統源碼(PC/UniAPP)

提供PC版本、UniAPP版本(高級授權)、支持多規格商品、優惠券、積分兌換、快遞鳥電子面單、支持移動端樣式、統計報表等 提供全部前后臺無加密源代碼、數據庫離線部署。 構建您的在線商店的基石 一、引言&#xff1a;為什么選擇簡單商城系統源碼&#xff1f; 在數字化時代&am…

【Spring Cloud Alibaba】初識Spring Cloud Alibaba

目錄 回顧主流的微服務框架Spring Cloud 版本簡介Spring Cloud以往的版本發布順序排列如下&#xff1a; 由停更引發的"升級慘案"哪些Netflix組件被移除了&#xff1f; 替換方案服務注冊中心&#xff1a;服務調用&#xff1a;負載均衡&#xff1a;服務降級&#xff1a…

Python—面向對象小解(6)-閉包、裝飾器

一、閉包 在Python中&#xff0c;閉包&#xff08;closure&#xff09;是一個函數對象&#xff0c;即使在其詞法作用域外被調用&#xff0c;它仍然能訪問該作用域內的變量。閉包通過“捕獲”周圍作用域的變量&#xff0c;保持這些變量的狀態&#xff0c;即使在外部函數已經返回…

干貨分享 | TSMaster 中 Hex 文件編輯器使用詳細教程

TSMaster 軟件的 Hex 文件編輯器提供了文件處理的功能&#xff0c;這一特性讓使用 TSMaster 軟件的用戶可以更便捷地對 Hex、bin、mot、s19 和 tsbinary 類型的文件進行處理。 本文重點講述 TSMaster 中 Hex 文件編輯器的使用方法&#xff0c;該編輯器能實現將現有的 Hex、bin、…

@vue-office/excel 解決移動端預覽excel文件觸發軟鍵盤

先直接上代碼 不耽誤大家時間 標明下插件庫 非常感謝作者提供預覽插件 vue-office/excel 只需要控制CSS :deep(.x-spreadsheet-overlayer) {.x-spreadsheet-selectors {display: none !important;} } :deep(.x-spreadsheet-bottombar) {li.active {user-select: none !import…

家政上門系統源碼,家政上門預約服務系統開發涉及的主要功能

家政上門預約服務系統開發是指建立一個在線平臺或應用程序&#xff0c;用于提供家政服務的預約和管理功能。該系統的目標是讓用戶能夠方便地預約各種家政服務&#xff0c;如保潔、家庭護理、月嫂、家電維修等&#xff0c;并實現服務供應商管理和訂單管理等功能。 以下是開發家政…

Windows API 速查

Windows API 函數大全 (推薦)&#xff1a;https://blog.csdn.net/xiao_yi_xiao/article/details/121604742Windows API 在線參考手冊&#xff1a;http://www.office-cn.net/t/api/index.html?web.htmWindows 開發文檔 (官方)&#xff1a;https://learn.microsoft.com/zh-cn/wi…

linux驅動學習(三)之uboot與內核編譯

需要板子一起學習的可以這里購買&#xff08;含資料&#xff09;&#xff1a;點擊跳轉 GEC6818內核源碼下載&#xff1a;點擊跳轉 一、環境配置 由于GEC6818對應是64位系統&#xff0c;虛擬機中的linux系統也要是64位&#xff0c;比如&#xff1a;ubuntu16.04.rar …

Bee 支持 與 mybatis-plus 混用嗎?

Bee 支持 與 mybatis-plus 混用嗎&#xff1f; 你是在什么場景下要混用呢? mybatis-plus是基于mybatis. 而Bee本身就是一個ORM框架了. Hibernate/MyBatis plus Sharding JDBC Jpa Spring data GraphQL App ORM (Android, 鴻蒙) Bee Bee支持的數據庫 1.MySQL 2.Oracle 3.SQL…

elasticsearch的常規操作--增刪改查和批量處理

1、_cat 查詢 GET /_cat/nodes&#xff1a; 查看所有節點 GET /_cat/health&#xff1a; 查看es 健康狀況 GET /_cat/master&#xff1a; 查看主節點 GET /_cat/indices&#xff1a;查看所有索引show databases; 2、索引一個文檔&#xff08;保存&#xff09; 保存一個數據&…

某紅書旋轉滑塊驗證碼分析與協議算法實現(高通過率)

文章目錄 1. 寫在前面2. 接口分析3. 驗證軌跡4. 算法還原 【&#x1f3e0;作者主頁】&#xff1a;吳秋霖 【&#x1f4bc;作者介紹】&#xff1a;擅長爬蟲與JS加密逆向分析&#xff01;Python領域優質創作者、CSDN博客專家、阿里云博客專家、華為云享專家。一路走來長期堅守并致…

力扣SQL50 學生們參加各科測試的次數 查詢 三表查詢

Problem: 1280. 學生們參加各科測試的次數 &#x1f468;?&#x1f3eb; 參考題解 join等價于inner join&#xff0c;不用關聯條件的join等價于cross join Code select stu.student_id,stu.student_name, sub.subject_name,count(e.subject_name) attended_exams from Stud…

關于windosw打開安全中心空白的解決方案

關于windosw打開安全中心空白的解決方案 問題如下 問題如下 之后點擊一片空白 解決方案如下 按下WINR&#xff0c;輸入regedit回車找到路徑&#xff1a;“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SecurityHealthService”&#xff0c;然后雙擊右邊的“start”…

【最新鴻蒙應用開發】——關系型數據庫簡單上手(RDB)

關系型數據庫&#xff08;RDB&#xff09; 關系型數據庫&#xff08;Relational Database&#xff0c;RDB&#xff09;是一種基于關系模型來管理數據的數據庫。關系型數據庫基于SQLite組件提供了一套完整的對本地數據庫進行管理的機制&#xff0c;對外提供了一系列的增、刪、改…