C++List模擬實現|細節|難點|易錯點|全面解析|類型轉換|

目錄

1.模擬代碼全部

2.四大塊代碼理解

1.最底層:ListNode部分

2.第二層:ListIterator部分

3.第三層:ReserveListIterator部分

?4最終層:List


1.模擬代碼全部

using namespace std;
template<class T>
struct ListNode
{T _Val;ListNode<T>* Prev;ListNode<T>* Next;ListNode(T Val=T()){Prev = nullptr;Next = nullptr;_Val = Val;}
};
template<class T, class Ref, class Ptr>
class ListIterator
{
public:typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;typedef Ref Ref;typedef Ptr Ptr;ListIterator(Node* _NODE = nullptr) :_node(_NODE){}Ptr operator->(){return &(operator*());}Ref operator*(){return _node->_Val;}Self& operator++(){_node = _node->Next;return *this;}Self operator++(int){Node* Newnode = _node;_node = _node->Next;return Newnode;}Self& operator--(){_node = _node->Prev;return *this;}Self operator--(int){Node* Newnode = _node;_node = _node->Prev;return Newnode;}bool operator==(const Self& I) const{if (I._node == _node){return true;}else{return false;}}bool operator!=(const Self& I)const{if (I._node != _node){return true;}else{return false;}}Node* _node;
};
template<class Iterator>
class ReserveListIterator
{
public:typedef typename Iterator::Ptr Ptr;typedef typename Iterator::Ref Ref;typedef ReserveListIterator<Iterator> Self;ReserveListIterator(Iterator it):_it(it){}Ref operator*(){Iterator temp(_it);temp--;return *temp;}Ptr operator->(){return &(operator*());}Self operator++(){_it++;return *this;}Self operator++(int){Iterator temp(_it);_it++;return *temp;}Self operator--(){_it--;return *this;}Self operator--(int){Iterator temp(_it);_it--;return *temp;}bool operator == (const Self & I) const{if (I._it==_it){return true;}else{return false;}}bool operator !=(const Self& I)const{if (I._it != _it){return true;}else{return false;}}Iterator _it;
};
template<class T>
class List
{typedef ListNode<T> Node;typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;typedef ReserveListIterator<iterator> reverse_iterator;typedef ReserveListIterator<const_iterator> const_reverse_iterator;
public:List(){creathead();}List(int n,const T& Value=T()){creathead();for (int i = 0; i < n; i++){push_back(Value);}}template <class Iterator>List(Iterator first, Iterator last){creathead();while (first != last){push_back(*first);first++;}}List(const List<T>& l){creathead();List<T>temp(l.begin(), l.end());this->swap(temp);}List<T>& operator=(List<T> l){List<T>temp(l);this->swap(temp);return *this;}~List(){clear();delete _head;_head = nullptr;}iterator begin(){return _head->Next;}iterator end(){return _head;}const_iterator begin()const{return _head->Next;}const_iterator end()const{return _head;}reverse_iterator rbegin(){return reverse_iterator(begin());}reverse_iterator rend(){return reverse_iterator(end());}const_reverse_iterator rbegin()const{return const_reverse_iterator(begin());}const_reverse_iterator rend()const{return const_reverse_iterator(end());}size_t size()const{size_t num = 0;Node* CUR = _head->Next;while (CUR != _head){num++;CUR = CUR->Next;}return num;}bool empty()const{if (begin() == end()){return true;}else{return false;}}void resize(size_t newsize, const T& data = T()){if (newsize > size()){Node* it = end();it = it->Prev;for (size_t i = size(); i < newsize; i++){Node* cur = new Node(data);cur->Next = it->Next;cur->Prev = it;it->Next = cur;}}else{Node* it = end();size_t len = size() - newsize;while (len--){Node* cur = it;it = it->Prev;delete cur;}it->Next = _head;_head->Prev = it;}}T& front(){return *begin();}const T& front()const{return *begin();}T& back(){iterator it = end();it--;return *it;}const T& back()const{iterator it = end();it--;return *it;}void push_back(const T& val){Node* Newnode = new Node(val);Node* cur = _head->Prev;cur->Next = Newnode;_head->Prev = Newnode;Newnode->Next = _head;Newnode->Prev = cur;}void pop_back(){Node* cur = _head->Prev->Prev;Node* popnode = _head->Prev;cur->Next = _head;_head->Prev = cur;delete popnode;}void push_front(const T& val){Node* cur = _head->Next;Node* newnode = new Node(val);_head->Next = newnode;cur->Prev = newnode;newnode->Next = cur;newnode->Prev = _head;}void pop_front(){Node* cur = _head->Next->Next;Node* popnode = _head->Next;_head->Next = cur;cur->Prev = _head;delete popnode;}iterator insert(iterator pos, const T& val){Node* pre = pos._node->Prev;Node* nect = pos._node;Node* newnode = new Node(val);newnode->Prev = pre;newnode->Next = nect;pre->Next = newnode;nect->Prev = newnode;return newnode;}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->Prev;Node* next = cur->Next;delete cur;prev->Next = next;next->Prev = prev;return next;}void clear(){size_t sz = this->size();while (sz--){Node* cur = _head->Next;Node* pop;}}void swap(List<T>& l){Node* temp = l._head;l._head = _head;_head = temp;}void creathead(){_head = new Node(0);_head->Prev = _head;_head->Next = _head;}
private:Node* _head;
};

2.四大塊代碼理解

代碼一共分為四塊,我們分開來理解

1.最底層:ListNode部分

這里是最簡單的部分,小伙伴們應該都看的懂吧

using namespace std;
template<class T>
struct ListNode
{T _Val;ListNode<T>* Prev;ListNode<T>* Next;ListNode(T Val=T()){Prev = nullptr;Next = nullptr;_Val = Val;}
};

?這里我們形象點記憶

其實應該不用贅述多了,基礎好的同學看到這張圖應該就差不多懂了。?

唯一要注意的是

T Val=T()

>>? ? T()表示對類型T進行值初始化,生成一個臨時的右值

>>? ? 如果T是內置類型(如int,double,char等),則T()會執行零初始化,即返回0,0.0或'\0'等默認值。

>>? ? 如果T是類類型,則T()會調用默認構造函數(如果存在)

聰明的小伙伴已經理解清楚了

2.第二層:ListIterator部分

聰明的小伙伴應該看代碼就能懂了

那么我在這下方陳述了一些難點和易錯點?

template<class T, class Ref, class Ptr>
class ListIterator
{
public:typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;typedef Ref Ref;typedef Ptr Ptr;ListIterator(Node* _NODE = nullptr) :_node(_NODE){}Ref operator*(){return _node->_Val;}Self& operator++(){_node = _node->Next;return *this;}Self operator++(int){Node* Newnode = _node;_node = _node->Next;return Newnode;}Self& operator--(){_node = _node->Prev;return *this;}Self operator--(int){Node* Newnode = _node;_node = _node->Prev;return Newnode;}bool operator==(const Self& I) const{if (I._node == _node){return true;}else{return false;}}bool operator!=(const Self& I)const{if (I._node != _node){return true;}else{return false;}}Node* _node;
};

聰明的小伙伴應該看代碼就能懂了

那么我在這陳述一下一些難點和易錯點?

>>? ??typedef Ref Ref和typedef Ptr Ptr,簡單來說,我們需要讓編譯器知道Listiterator里面有Ptr和 Ref,后面的反向迭代器ReserveListIterator來使用Listiterator的Ref和Ptr

>>? ? Ref:Ref在后面我們會通過T&來填充這塊模板,也就是說Ref就是引用

>>? ? Ptr:Ptr在后面我們會通過T*來填充這塊模板,也就是說Ptr就是指針

3.第三層:ReserveListIterator部分

聰明的小伙伴直接看代碼

template<class Iterator>
class ReserveListIterator
{
public:typedef typename Iterator::Ptr Ptr;typedef typename Iterator::Ref Ref;typedef ReserveListIterator<Iterator> Self;ReserveListIterator(Iterator it):_it(it){}Ref operator*(){Iterator temp(_it);temp--;return *temp;}Ptr operator->(){return &(operator*());}Self operator++(){_it++;return *this;}Self operator++(int){Iterator temp(_it);_it++;return *temp;}Self operator--(){_it--;return *this;}Self operator--(int){Iterator temp(_it);_it--;return *temp;}bool operator == (const Self & I) const{if (I._it==_it){return true;}else{return false;}}bool operator !=(const Self& I)const{if (I._it != _it){return true;}else{return false;}}Iterator _it;
};

?

>>? ? 之前我們在ListIterator里重新定義了Ptr和Ref參數就是留在ReserveListIterator使用

?

這里要注意一定不要寫成Iterator &,本人之前就因為這個錯誤導致費了1小時/(ㄒoㄒ)/~~?

?4最終層:List

牛人已經看代碼就懂了

template<class T>
class List
{typedef ListNode<T> Node;typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;typedef ReserveListIterator<iterator> reverse_iterator;typedef ReserveListIterator<const_iterator> const_reverse_iterator;
public:List(){creathead();}List(int n,const T& Value=T()){creathead();for (int i = 0; i < n; i++){push_back(Value);}}template <class Iterator>List(Iterator first, Iterator last){creathead();while (first != last){push_back(*first);first++;}}List(const List<T>& l){creathead();List<T>temp(l.begin(), l.end());this->swap(temp);}List<T>& operator=(List<T> l){List<T>temp(l);this->swap(temp);return *this;}~List(){clear();delete _head;_head = nullptr;}iterator begin(){return _head->Next;}iterator end(){return _head;}const_iterator begin()const{return _head->Next;}const_iterator end()const{return _head;}reverse_iterator rbegin(){return reverse_iterator(begin());}reverse_iterator rend(){return reverse_iterator(end());}const_reverse_iterator rbegin()const{return const_reverse_iterator(begin());}const_reverse_iterator rend()const{return const_reverse_iterator(end());}size_t size()const{size_t num = 0;Node* CUR = _head->Next;while (CUR != _head){num++;CUR = CUR->Next;}return num;}bool empty()const{if (begin() == end()){return true;}else{return false;}}void resize(size_t newsize, const T& data = T()){if (newsize > size()){Node* it = end();it = it->Prev;for (size_t i = size(); i < newsize; i++){Node* cur = new Node(data);cur->Next = it->Next;cur->Prev = it;it->Next = cur;}}else{Node* it = end();size_t len = size() - newsize;while (len--){Node* cur = it;it = it->Prev;delete cur;}it->Next = _head;_head->Prev = it;}}T& front(){return *begin();}const T& front()const{return *begin();}T& back(){iterator it = end();it--;return *it;}const T& back()const{iterator it = end();it--;return *it;}void push_back(const T& val){Node* Newnode = new Node(val);Node* cur = _head->Prev;cur->Next = Newnode;_head->Prev = Newnode;Newnode->Next = _head;Newnode->Prev = cur;}void pop_back(){Node* cur = _head->Prev->Prev;Node* popnode = _head->Prev;cur->Next = _head;_head->Prev = cur;delete popnode;}void push_front(const T& val){Node* cur = _head->Next;Node* newnode = new Node(val);_head->Next = newnode;cur->Prev = newnode;newnode->Next = cur;newnode->Prev = _head;}void pop_front(){Node* cur = _head->Next->Next;Node* popnode = _head->Next;_head->Next = cur;cur->Prev = _head;delete popnode;}iterator insert(iterator pos, const T& val){Node* pre = pos._node->Prev;Node* nect = pos._node;Node* newnode = new Node(val);newnode->Prev = pre;newnode->Next = nect;pre->Next = newnode;nect->Prev = newnode;return newnode;}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->Prev;Node* next = cur->Next;delete cur;prev->Next = next;next->Prev = prev;return next;}void clear(){size_t sz = this->size();while (sz--){Node* cur = _head->Next;Node* pop;}}void swap(List<T>& l){Node* temp = l._head;l._head = _head;_head = temp;}void creathead(){_head = new Node(0);_head->Prev = _head;_head->Next = _head;}
private:Node* _head;
};

?這里要注意一下轉換順序,listnode不能直接轉換為reverse_iterator?

listnode轉換為reverse_iterator需要兩個個過程

?

?易錯點難點就是以上那么多了,說多了只會妨礙小伙伴們,通過自己學習效率才是最高的。

3.測試代碼?

#include"LList.h"
#include<iostream>
void ListPrint(List<int> it)
{auto i = it.begin();while(i!=it.end()){cout << *i << " ";i++;}
}
void TestBiteList1()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };List<int> l3(array, array + sizeof(array) / sizeof(array[0]));ListPrint(l3);ListIterator<int, int&, int*> it(l3.begin());}
void TestBiteList2()
{List<int> l;l.push_back(1);l.push_back(2);l.push_back(3);ListPrint(l);l.pop_back();l.pop_back();ListPrint(l);l.pop_back();cout << l.size() << endl;l.push_front(1);l.push_front(2);l.push_front(3);ListPrint(l);l.pop_front();l.pop_front();ListPrint(l);l.pop_front();cout << l.size() << endl;
}
void TestBiteList3()
{int array[] = { 1, 2, 3, 4, 5 };List<int> l(array, array + sizeof(array) / sizeof(array[0]));auto pos = l.begin();l.insert(l.begin(), 0);ListPrint(l);++pos;l.insert(pos, 2);ListPrint(l);l.erase(l.begin());l.erase(pos);ListPrint(l);cout << *pos << endl;auto it = l.begin();while (it != l.end()){it = l.erase(it);}cout << l.size() << endl;
}
void TestBiteList4()
{int array[] = { 1, 2, 3, 4, 5 };List<int> l(array, array + sizeof(array) / sizeof(array[0]));auto rit = l.rbegin();while (rit != l.rend()){cout << *rit << " ";++rit;}cout << endl;const List<int> cl(l);auto crit = l.rbegin();while (crit != l.rend()){cout << *crit << " ";++crit;}cout << endl;
}
int main()
{TestBiteList1();TestBiteList2();TestBiteList3();TestBiteList4();
}

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

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

相關文章

【深度學習與實戰】2.1、線性回歸模型與梯度下降法先導

import numpy as np# 數據準備 X np.array([1, 2, 3]) y np.array([3, 5, 7])# 參數初始化 w0, w1 0, 0 alpha 0.1 n len(X)# 迭代10次 for epoch in range(10):# 計算預測值y_pred w1 * X w0# 計算梯度grad_w0 (1/n) * np.sum(y_pred - y)grad_w1 (1/n) * np.sum((y_…

銳捷EWEB路由器 timeout.php任意文件上傳漏洞代碼審計(DVB-2025-9003)

免責聲明 僅供網絡安全研究與教育目的使用。任何人不得將本文提供的信息用于非法目的或未經授權的系統測試。作者不對任何由于使用本文信息而導致的直接或間接損害承擔責任。如涉及侵權,請及時與我們聯系,我們將盡快處理并刪除相關內容。 一:產品介紹 銳捷EWEB路由器是銳…

flask開發中設置Flask SQLAlchemy 的 db.Column 只存儲非負整數(即 0 或正整數)

如果你想控制一個 Flask SQLAlchemy 的 db.Column 只存儲非負整數&#xff08;即 0 或正整數&#xff09;&#xff0c;你可以在模型中使用驗證來確保這一點。一種常見的方法是使用模型的 validate 方法或者在執行插入或更新操作時進行檢查。 以下是實現這一目標的幾種方法&…

sqlmap 源碼閱讀與流程分析

0x01 前言 還是代碼功底太差&#xff0c;所以想嘗試閱讀 sqlmap 源碼一下&#xff0c;并且自己用 golang 重構&#xff0c;到后面會進行 ysoserial 的改寫&#xff1b;以及 xray 的重構&#xff0c;當然那個應該會很多參考 cel-go 項目 0x02 環境準備 sqlmap 的項目地址&…

vscode連接服務器失敗問題解決

文章目錄 問題描述原因分析解決方法徹底刪除VS Code重新安裝較老的版本 問題描述 vscode鏈接服務器時提示了下面問題&#xff1a; 原因分析 這是說明VScode版本太高了。 https://code.visualstudio.com/docs/remote/faq#_can-i-run-vs-code-server-on-older-linux-distribu…

企業網站源碼HTML成品網站與網頁代碼模板指南

在當今數字化時代&#xff0c;企業網站已成為展示品牌形象、吸引客戶和提供在線服務的重要工具。對于許多企業來說&#xff0c;使用現成的HTML網站源碼模板是快速搭建網站的高效方式。本文將詳細介紹企業網站源碼、HTML成品網站以及網頁代碼模板的相關內容&#xff0c;幫助你快…

計算機網絡 - OSI 七層模型

OSI 七層模型 OSI&#xff08;Open System Interconnection&#xff0c;開放系統互聯&#xff09;模型由 ISO&#xff08;國際標準化組織&#xff09; 制定&#xff0c;目的是為不同計算機網絡系統之間的通信提供一個標準化的框架。它將網絡通信劃分為 七個層次&#xff0c;每…

flutter-實現瀑布流布局及下拉刷新上拉加載更多

文章目錄 1. 效果預覽2. 結構分析3. 完整代碼4. 總結 1. 效果預覽 在 Flutter 應用開發中&#xff0c;瀑布流布局常用于展示圖片、商品列表等需要以不規則但整齊排列的內容。同時&#xff0c;下拉刷新和上拉加載更多功能&#xff0c;能夠極大提升用戶體驗&#xff0c;讓用戶方…

在 Ubuntu 下通過 Docker 部署 Nginx 服務器

1. Docker 和 Nginx 簡介以及實驗環境 Docker 是一個開源的容器化平臺&#xff0c;允許開發者將應用程序及其依賴項打包成一個輕量級的、可移植的容器。通過 Docker&#xff0c;開發者可以在任何支持 Docker 的環境中運行應用&#xff0c;從而實現一致的開發和生產環境。Docke…

IoT平臺實時監測機器人狀態的實現方案

通過IoT平臺實時監測機器人狀態的實現方案與可執行路徑 一、整體架構設計 #mermaid-svg-6xMlDfFSZM4Wc8tA {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-6xMlDfFSZM4Wc8tA .error-icon{fill:#552222;}#mermaid-sv…

mybatis里in關鍵字拼接id問題

我們一般會把ids集合用StrUtil.join(‘,’)轉成"1,2,3"這種形式 然后放入in中 我們會這么寫: select id, nick_name, icon from tb_user where id in (#{ids}) order by FIELD(id, #{ids})結果發現sql執行是這樣的: select id, nick_name, icon from tb_user where…

4.用 Excel 錄入數據

一 用 Excel 錄入數據的兩種方式 用鼠標鍵盤錄入數據和從網上爬取數據。 二 用鼠標鍵盤錄入數據 1.錄入數據的規范 橫著錄入數據&#xff08;橫著一條條錄入數據&#xff09;。 2.使用快捷鍵進行數據錄入 tab 鍵和 enter 鍵。 tab 鍵&#xff1a;向右移動一個單元格。 tab 鍵…

C++類與對象-3.23筆記

今天學習了類的概述和寫類的基本框架 在嗶哩嗶哩學習的這個老師的C面向對象高級語言程序設計教程&#xff08;118集全&#xff09;講的很不錯&#xff08;真的&#xff01;&#xff01;&#xff01;&#xff09;&#xff0c;C語言也是在這個老師的帶領下學習的 #include<io…

Android讀寫權限分析

Android系統使用的是Linux內核&#xff0c;所以Android系統沿用了linux系統的那一套文件讀寫權限。 目錄 1&#xff0c;權限解讀1.1&#xff0c;權限分為三種類型&#xff1a;1.2&#xff0c;權限針對的三類對象&#xff1a;1.3&#xff0c;文件和目錄的權限區別1.3.1&#xf…

Python二分查找【清晰易懂】

1. 二分查找是什么&#xff1f; 想象你在玩“猜數字”游戲&#xff1a; 對方心里想一個 1~100 的數字&#xff0c;你每次猜一個數&#xff0c;對方會告訴你是“大了”還是“小了”。 最快的方法&#xff1a;每次都猜中間的數&#xff01;比如第一次猜50&#xff0c;如果大了&…

關于Qt的各類問題

目錄 1、問題&#xff1a;Qt中文亂碼 2、問題&#xff1a;啟動時避免ComBox控件出現默認值 博客會不定期的更新各種Qt開發的Bug與解決方法,敬請關注! 1、問題&#xff1a;Qt中文亂碼 問題描述&#xff1a;我在設置標題時出現了中文亂碼 this->setWindowTitle("算法…

關于我對接了deepseek之后部署到本地將數據存儲到mysql的過程

寫在前面 今天寫一下使用nodejs作為服務端&#xff0c;vue作為客戶端&#xff0c;mysql的數據庫&#xff0c;對接deepseek的全過程&#xff0c;要實現一個很簡單的效果就是&#xff0c;可以自由的詢問&#xff0c;然后可以將詢問的過程存儲到mysql的數據庫中。 文檔對接 deeps…

游戲引擎學習第182天

回顧和今天的計劃 昨天的進展令人驚喜&#xff0c;原本的調試系統已經被一個新的系統完全替換&#xff0c;新系統不僅能完成原有的所有功能&#xff0c;還能捕獲完整的調試信息&#xff0c;包括時間戳等關鍵數據。這次的替換非常順利&#xff0c;效果很好。 今天的重點是在此基…

CSS終極指南:從基礎到高級實踐

目錄 一、CSS基礎概念與核心語法 1.1 CSS的本質與作用 1.2 CSS語法結構 二、CSS與HTML結合的四種方式 2.1 內聯樣式&#xff08;Inline Style&#xff09; 2.2 內部樣式表&#xff08;Internal Style Sheet&#xff09; 2.3 外部樣式表&#xff08;External Style Sheet…

MATLAB 2024b深度學習新特性全面解析與DeepSeek大模型集成開發

MATLAB 2024b深度學習工具箱通過架構創新與功能強化&#xff0c;為科研創新和行業應用提供了全棧式解決方案。 第一&#xff1a;MATLAB 2024b深度學習工具箱新特性 1、MATLAB Deep Learning Toolbox 2、實時腳本&#xff08;Live Script&#xff09;與交互控件&#xff08…