C++學習之路,從0到精通的征途:List類的模擬實現

目錄

一.list的介紹

二.list的接口實現

1.結點

2.list結構

3.迭代器?

(1)begin

(2)end

?4.修改

(1)insert

(2)push_back

(3)push_front

(4)erase

(5)pop_back

(6)pop_front

(7)swap

(8)clear?

5.默認成員函數

(1)構造函數

(2)拷貝構造函數

(3)賦值重載

(4)析構函數

三.代碼總覽

list.h

test.cpp


?

一.list的介紹

源文檔

二.list的接口實現

1.結點

template<class T>
struct list_node
{list_node* _prev;list_node* _next;T _data;// 由于數據類型由模板參數決定,所以缺省值給匿名對象list_node(const T& x = T()):_prev(nullptr),_next(nullptr),_data(x){}
};

? ? ? ? 用一個結構體來封裝結點,我們手動寫默認構造函數以便在申請結點時調用。

2.list結構

template<class T>
class list
{// 結點typedef list_node<T> Node;
public:// 在類域外訪問// 迭代器typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;
private:// 哨兵位Node* _head;// 有效數據個數size_t _size = 0;
};

3.迭代器?

? ? ? ? list的迭代器與之前的string和vector不同,由于list的數據存儲空間并不是連續的,所以我們無法再繼續用原生指針來實現迭代器類型,++,解引用等操作并不能實現想要達到的目的,所以我們需要重載這些操作符,并將迭代器封裝成一個新的類。

template<class T, class Ref, class Ptr>
struct list_iterator
{typedef list_node<T> Node;typedef list_iterator<T, Ref, Ptr> Self;Node* _node; // 迭代器所指向的結點list_iterator(Node* node):_node(node){}// 比較指向的結點是否相同bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}// Ref來控制iterator與const_iterator// Ref->T& -- iterator;// Ref->const T& -- const_iterator;// 獲取結點存儲的數據Ref operator*(){return _node->_data;}// 使迭代器指向下一個結點Self& operator++(){_node = _node->_next;return *this;}// 后置++Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}// 使迭代器指向前一個結點Self& operator--(){_node = _node->_prev;return *this;}// 前置--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}// 為了可讀性進行特殊處理 it->->_a1 被優化為 it->_a1// Ptr來控制iterator與const_iterator// Ptr->T* -- iterator// Ptr->const T* -- const_iteratorPtr operator->(){return &_node->_data;}
};

(1)begin

iterator begin()
{return iterator(_head->_next);
}
const_iterator begin() const
{return const_iterator(_head->_next);
}

(2)end

iterator end()
{// 返回尾結點的下一個結點,也就是哨兵位return iterator(_head);
}
const_iterator begin() const
{return const_iterator(_head->_next);
}

?4.修改

(1)insert

void insert(iterator pos, const T& x)
{// 申請新結點的空間,調用構造Node* newnode = new Node(x);// 斷開舊連接,連接新結點Node* cur = pos._node;Node* prev = cur->_prev;// prev newnode curnewnode->_prev = prev;newnode->_next = cur;prev->_next = newnode;cur->_prev = newnode;++_size;
}

(2)push_back

void push_back(const T& x)
{//Node* newnode = new Node(x);//Node* tail = _head->_prev;tail newnode _head//newnode->_prev = tail;//newnode->_next = _head;//tail->_next = newnode;//_head->_prev = newnode;insert(end(), x);
}

(3)push_front

void push_front(const T& x)
{insert(begin(), x);
}

(4)erase

iterator erase(iterator pos)
{Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;//return iterator(next);// 為防止迭代器失效,返回刪除后的下一個結點的迭代器// 單參數構造函數支持隱式轉換return next;
}

? ? ? ? 為防止erase后,pos依然指向被delete的結點從而導致迭代器失效,erase返回指向下一個結點的迭代器。?

(5)pop_back

void pop_back()
{erase(--end());
}

(6)pop_front

void pop_front()
{erase(begin());
}

(7)swap

void swap(list<T>& lt)
{std::swap(_head, lt._head);std::swap(_size, lt._size);
}

? ? ? ? 交換哨兵位即可交換兩個list。

(8)clear?

void clear()
{auto it = begin();while (it != end()){it = erase(it);}
}

? ? ? ? 除了哨兵位,其他結點逐個erase。?

5.默認成員函數

(1)構造函數

空list申請哨兵位:empty_init

// 空list申請哨兵位
void empty_init()
{_head = new Node;_head->_prev = _head;_head->_next = _head;
}// 無參數構造
list()
{//_head = new Node;//_head->_prev = _head;//_head->_next = _head;empty_init();
}// initializer_list構造
list(std::initializer_list<T> il)
{empty_init();for (auto& e : il){push_back(e);}
}

(2)拷貝構造函數

list(const list<T>& lt)
{empty_init();for (auto& e : lt){push_back(e);}
}

? ? ? ? 先申請哨兵位,再逐個尾插即可。

(3)賦值重載

list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}

(4)析構函數

~list()
{clear();delete _head;_head = nullptr;
}

三.代碼總覽

list.h

#include<iostream>
#include<initializer_list>namespace my_list
{template<class T>struct list_node{list_node* _prev;list_node* _next;T _data;// 由于數據類型由模板參數決定,所以缺省值給匿名對象list_node(const T& x = T()):_prev(nullptr),_next(nullptr),_data(x){}};template<class T, class Ref, class Ptr>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T, Ref, Ptr> Self;Node* _node; // 迭代器所指向的結點list_iterator(Node* node):_node(node){}// 比較指向的結點是否相同bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}// Ref來控制iterator與const_iterator// Ref->T& -- iterator;// Ref->const T& -- const_iterator;// 獲取結點存儲的數據Ref operator*(){return _node->_data;}// 使迭代器指向下一個結點Self& operator++(){_node = _node->_next;return *this;}// 后置++Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}// 使迭代器指向前一個結點Self& operator--(){_node = _node->_prev;return *this;}// 前置--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}// 為了可讀性進行特殊處理 it->->_a1 被優化為 it->_a1// Ptr來控制iterator與const_iterator// Ptr->T* -- iterator// Ptr->const T* -- const_iteratorPtr operator->(){return &_node->_data;}};template<class T>class list{// 結點typedef list_node<T> Node;public:// 迭代器typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;// 空list申請哨兵位void empty_init(){_head = new Node;_head->_prev = _head;_head->_next = _head;}// 無參數構造list(){//_head = new Node;//_head->_prev = _head;//_head->_next = _head;empty_init();}// initializer_list構造list(std::initializer_list<T> il){empty_init();for (auto& e : il){push_back(e);}}list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}// lt2 = lt1list<T>& operator=(list<T> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}size_t size(){return _size;}iterator begin(){return iterator(_head->_next);}iterator end(){// 返回尾結點的下一個結點,也就是哨兵位return iterator(_head);}const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}void push_back(const T& x){//Node* newnode = new Node(x);//Node* tail = _head->_prev;tail newnode _head//newnode->_prev = tail;//newnode->_next = _head;//tail->_next = newnode;//_head->_prev = newnode;insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void insert(iterator pos, const T& x){// 申請新結點的空間,調用構造Node* newnode = new Node(x);// 斷開舊連接,連接新結點Node* cur = pos._node;Node* prev = cur->_prev;// prev newnode curnewnode->_prev = prev;newnode->_next = cur;prev->_next = newnode;cur->_prev = newnode;++_size;}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;//return iterator(next);// 為防止迭代器失效,返回刪除后的下一個結點的迭代器// 單參數構造函數支持隱式轉換return next;}private:// 哨兵位Node* _head;// 有效數據個數size_t _size = 0;};
}

test.cpp

#include"list.h"
using namespace std;namespace my_list
{void test_list1(){list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int>::iterator it = lt1.begin();while (it != lt1.end()){*it += 10;cout << *it << " ";++it;}cout << endl;lt1.push_back(1);lt1.push_back(2);lt1.push_front(3);lt1.push_front(4);for (auto& e : lt1){cout << e << " ";}cout << endl;lt1.pop_back();lt1.pop_front();for (auto& e : lt1){cout << e << " ";}cout << endl;cout << lt1.size() << endl;}void test_list2(){list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_front(3);lt1.push_front(4);for (auto& e : lt1){cout << e << " ";}cout << endl;list<int> lt2(lt1);for (auto& e : lt1){cout << e << " ";}cout << endl;list<int> lt3;lt3 = lt1;for (auto& e : lt1){cout << e << " ";}}struct AA{int _a1;int _a2;AA(int a1 = 1, int a2 = 1):_a1(a1), _a2(a2){}};void test_list3(){list<int> lt1 = { 1,2,3,4 };for (auto& e : lt1){cout << e << " ";}cout << endl;list<AA> lt2 = { {1,1},{2,2},{3,3},{4,4} };list<AA>::iterator it = lt2.begin();while (it != lt2.end()){//cout << (*it)._a1 << ":" << (*it)._a2 << endl;//cout << it->->_a1 << ":" << it->->_a2 << endl;cout << it->_a1 << ":" << it->_a2 << endl;++it;}list<AA>::iterator lit = lt2.begin();while (lit != lt2.end()){cout << lit.operator->()->_a1 << ":" << lit.operator->()->_a2 << endl;++lit;}}
}int main()
{my_list::test_list3();return 0;
}

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

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

相關文章

【游戲ai】從強化學習開始自學游戲ai-2 使用IPPO自博弈對抗pongv3環境

文章目錄 前言一、環境設計二、動作設計三、狀態設計四、神經網路設計五、效果展示其他問題總結 前言 本學期的大作業&#xff0c;要求完成多智能體PPO的乒乓球對抗環境&#xff0c;這里我使用IPPO的方法來實現。 正好之前做過這個單個PPO與pong環境內置的ai對抗的訓練&#…

計算機考研精煉 操作系統

第 14 章 操作系統概述 14.1 基本概念 14.1.1 操作系統的基本概念 如圖 14 - 1 所示&#xff0c;操作系統是計算機系統中的一個重要組成部分&#xff0c;它位于計算機硬件和用戶程序&#xff08;用戶&#xff09;之間&#xff0c;負責管理計算機的硬件資源&#xff0c;為用戶和…

什么是基爾霍夫第一定律

基爾霍夫第一定律&#xff08;Kirchhoffs First Law&#xff09;&#xff0c;也稱為基爾霍夫電流定律&#xff08;Kirchhoffs Current Law&#xff0c;簡稱 KCL&#xff09;&#xff0c;是電路分析中最基礎的定律之一。它描述了電路中電流的守恒特性&#xff0c;適用于任何集總…

解決 RN Switch 組件在安卓端樣式很丑的問題

解決此種問題的方式有很多 可以導入原生庫react-native-switch 切圖 (會缺少動畫) 使用 js 組件 這里使用 js 繪制組件&#xff08;原生體驗&#xff09;解決此類問題 Switch.tsx import React, { useEffect, useRef, useState } from react; import { Animated, Pressabl…

【AI】【MCP】搭建私人王炸MCP自動化工作流

目錄 一、什么是MCP 二、MCP大集合 三、準備工作 3.1 安裝node.js 3.2 安裝vscode 3.3 安裝cline插件 3.3.1 安裝 3.3.2 配置Cline 四、配置MCP服務 4.1 Search-mcp服務 4.2 playwright-mcp 服務 前言&#xff1a;夢想組合&#xff0c;輕松辦公&#xff0c;告別手動&a…

Git 實操:如何使用交互式 Rebase 移除指定提交(真實案例分享)

在日常開發中&#xff0c;有時候我們提交了一些不想保留的記錄&#xff0c;比如測試代碼、錯誤的功能提交等。 ?? 在操作 4. 強制推送到遠程倉庫前的注意事項 強制推送&#xff08;git push --force 或 git push -f&#xff09;確實很強大但也危險&#xff0c;因為它會重寫…

11.Excel:函數

一 函數是什么 函數是定義好的公式。 單元格內輸入sum然后tab&#xff0c;框選要求和的范圍&#xff0c;然后回車鍵。 補充&#xff1a;公式。 公式以開頭&#xff0c;可以用于計算&#xff0c;返回數值。 分別點擊各個數值&#xff0c;中間用加號連接。這樣很不方便&#xff…

Springboot使用ThreadLocal提供線程局部變量,傳遞登錄用戶名

文章目錄 概述使用創建ThreadLocalUtil工具類在登錄攔截器中使用ThreadLocal存儲登錄用戶名在/userInfo接口中獲取登錄用戶名 注意事項參考視頻 概述 使用 創建ThreadLocalUtil工具類 utils/ThreadLocalUtil.java package org.example.utils;/*** ThreadLocal 工具類*/ Supp…

1399. 統計最大組的數目

1399. 統計最大組的數目 題目鏈接&#xff1a;1399. 統計最大組的數目 代碼如下&#xff1a; class Solution { public:int countLargestGroup(int n) {int res 0;unordered_map<int, int> um;int maxValue 0;for (int i 1;i < n;i) {string value to_string(i);…

VS Code 插件Git History Diff 使用

右上角 查看單個文件記錄

數學建模論文手的學習日常01

目錄 一.要寫的內容&#xff1a; 二.文章標題&#xff1a; 三.摘要&#xff08;非常非常非常重要&#xff09; 四、關鍵詞&#xff1a; 五、問題重述 六、模型假設 七、符號說明 八、模型的建立與求解 九、模型的分析與檢驗 十、模型的評價、改進與推廣 十一、參考…

深度學習: AI 體育領域

一、引言 在科技與體育深度融合的當下&#xff0c;AI 體育逐漸成為推動體育行業變革的重要力量。深度學習憑借其強大的數據分析與模式識別能力&#xff0c;為 AI 體育帶來了全新的發展機遇。從運動員動作分析到智能健身指導&#xff0c;從賽事預測到運動康復輔助&#xff0c;深…

在 Ubuntu24.04 LTS 上 Docker 部署英文版 n8n 和 部署中文版 n8n-i18n-chinese

一、n8n 簡介 n8n 是一個低代碼&#xff08;Low-Code&#xff09;工作流自動化平臺&#xff0c;可以幫助用戶以非常簡單的方式創建自動化流程&#xff0c;連接不同的應用程序和服務。n8n的設計理念是為了讓復雜的工作流變得簡單易用&#xff0c;同時也支持高度的自定義&#xf…

《系統分析師-第三階段—總結(八)》

背景 采用三遍讀書法進行閱讀&#xff0c;此階段是第三遍。 過程 本篇總結第15章的內容 第15章 總結 系統運行與維護&#xff0c;系統經過測試交付之后&#xff0c;進入運行維護階段&#xff0c;維護分為系統運行、故障維護、系統評價和系統相關的策略。 疑問&#xff1a;…

LeetCode 1295.統計位數為偶數的數字:模擬

【LetMeFly】1295.統計位數為偶數的數字&#xff1a;模擬 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/find-numbers-with-even-number-of-digits/ 給你一個整數數組 nums&#xff0c;請你返回其中位數為 偶數 的數字的個數。 示例 1&#xff1a; 輸入&#xff1…

DDD是什么?電商系統舉例

一、DDD的基本概念 領域驅動設計&#xff08;Domain-Driven Design&#xff0c;簡稱DDD&#xff09;是由Eric Evans提出的一種軟件開發方法論&#xff0c;旨在應對復雜業務系統的設計和實現。它的核心思想是將軟件的設計與業務領域緊密結合&#xff0c;通過深入理解業務需求&a…

K8S ConfigMap 快速開始

一、什么是 ConfigMap&#xff1f; ConfigMap 是 Kubernetes 中用于存儲非敏感配置數據的 API 對象&#xff0c;支持以鍵值對&#xff08;Key-Value&#xff09;或文件的形式存儲配置&#xff0c;允許將配置與鏡像解耦&#xff0c;實現配置的集中管理和動態更新。 二、主要用…

Prometheus使用Recoding Rules優化性能

通過PromQL可以實時對Prometheus中采集到的樣本數據進行查詢&#xff0c;聚合以及其它各種運算操作。而在某些PromQL較為復雜且計算量較大時&#xff0c;直接使用PromQL可能會導致Prometheus響應超時的情況。這時需要一種能夠類似于后臺批處理的機制能夠在后臺完成這些復雜運算…

C++ RAII 編程范式詳解

C RAII 編程范式詳解 一、RAII 核心概念 RAII&#xff08;Resource Acquisition Is Initialization&#xff0c;資源獲取即初始化&#xff09; 是 C 的核心編程范式&#xff0c;通過將資源生命周期與對象生命周期綁定實現安全、自動化的資源管理。 核心原則&#xff1a; 資源…

Rust 學習筆記:枚舉與模式匹配

Rust 學習筆記&#xff1a;枚舉與模式匹配 Rust 學習筆記&#xff1a;枚舉與模式匹配定義枚舉&#xff08;Enum&#xff09;枚舉變量Option 枚舉及其相對于 NULL 的優勢match 和枚舉與 Option\<T\> 匹配match 應該是詳盡的Catch-all 模式和 _ 占位符使用 if let 和 let e…