【c++】list模擬實現

list的接口

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zjw
{template<class T>struct listnode    {listnode* <T>_next;listnode* <T>_prev;T _data;listnode(const T& x = T()):_prev(nulllptr),_next(nullptr),_data(x){}};template<class T>struct _list_iterator{typedef listnode <T>node;typedef _list_iterator<T>self;node* _node;_list_iterator(node* n):_node(n){}self& operator++(){}self& operator--(){}self operator++(int){}self operator--(int){}bool operator!=(const self& s){}bool operator==(const self& s){}T& operator(){}};template <class T>class list{    typedef listnode <T>node;public:typedef _list_iterator<T>  iterator;list(){empty_init();}void empty_init(){}iterator begin(){}iterator end(){}void clear(){}~list{}list(const list<T>& it){}void push_back(const T&x){}void push_front(const T& x){}void pop_back(){}void pop_front(){}void swap(list<T>& tmp){}list<T>& operator=(list<T>it){}iterator insert(iterator pos ,const T&x){}iterator erase(iterator pos){}private :node* _head;};}

迭代器前置++,前置–,后置++,后置–

self& operator++(){ _node= _node->next;return * this;}self& operator--(){_node = _node->_prev;return * this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}

迭代器重載等于,以及不等于,以及解引用訪問數據

         bool operator!=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}T& operator*(){return _node->_data;}

鏈表的默認構造,以及尾插,獲取鏈表的頭和尾巴,以及測試尾插函數

 list(){empty_init();}void empty_init(){_head = new node();_head->_prev = _head;_head->_next = _head;}iterator begin(){return _head->_next;}iterator end(){return _head;}void push_back(const T&x){node* newnode = new node(x);node* tail = _head->_prev;newnode->_next = _head;newnode->_prev = tail;tail->_next = newnode;_head->_prev = newnode;}

尾插測試,以及迭代器測試

 void test1(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout <<*it << " ";it++;}}

在這里插入圖片描述


const迭代器的實現

![在這里插入圖片描述](https://img-blog.csdnimg.cn/direct/811e5adc5cac4d7d82a43a8790aa1741.png

我們就可以新增兩個帶const的begin(),end(),權限平移就可以調動。

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

如果我們要修改迭代器所指向位置的值呢??
在這里插入圖片描述
我們應該如何模擬實現一個常量迭代器呢??
如果按照以下的方式,可以實現嗎??
在這里插入圖片描述

所以我們應該怎么實現呢??
在這里插入圖片描述
迭代器中的解引用函數,我們需要讓他的返回值不被修改,所以 這個函數的返回值加const 就好了,所以我們在實現一個類,這個類基本和普通迭代器的類一樣,只是在解引用函數上有區分。

	template<class T>struct const_list_iterator{typedef    listnode <T>  node;typedef const_list_iterator<T> self;node* _node;const_list_iterator(node* n):_node(n){}self& operator++(){_node = _node->_next;return *this;}self& operator--(){_node = _node->_prev;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator !=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}const T operator*(){return _node->_data;}};

在這里插入圖片描述

在這里插入圖片描述
這樣子,就實現了const 的迭代器,但是重新搞一個類好麻煩呀,于是有大佬就想出了在提供一個模板參數來解決這個問題
在這里插入圖片描述


->運算符重載函數

我們可以想一下什么時候會用到->,當指針it指向的是結構體的話,我們可以訪問使用
it->data,來訪問數據,也可先對指針解引用*it,*it表示拿到這個結構體,然后使用.來訪問(*it).data;

  T*  operator->(){return &_node->_data;}
	 struct AA{int a1;int a2;AA(int _a1=0,int _a2=0):a1(_a1),a2(_a2){}};

測試->

	 void test3(){list<AA>res; res.push_back(AA(1,1));res.push_back(AA(2, 2));res.push_back(AA(3, 3));res.push_back(AA(4, 4));list<AA> ::iterator it = res.begin();while (it != res.end()){cout << it.operator->()->a1<<":" << it.operator->()->a2 << endl;it++;}}

在這里插入圖片描述
在這里插入圖片描述


這里有一個問題就是->訪問也是取數據,但取到的數據能修改嗎?這就面臨和解引用取數據同樣的問題。
我們現在需要做的是const迭代器的不能被將修改,普通的可以修改值
在這里插入圖片描述
我發現這里和解引用那里不一樣的是,解引用那里是值不可被修改,這里是地址不可被修改
在這里插入圖片描述


=運算符重載賦值

	 void swap(list<T>& tmp){std::swap(_head, tmp._head);}list<T>& operator=(list<T>it){swap(it);return *this;}

賦值函數測試

 void test4(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret = res;list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}

在這里插入圖片描述


拷貝構造函數

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

這里與賦值不一樣的地方是賦值的話,之前的空間不用放著也沒用,就在原空間操作了;拷貝構造是重新開的空間,然后將原來數據尾插到新空間
拷貝構造函數測試

 void test5(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret(res);list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}

在這里插入圖片描述


insert函數和earse函數

因為之前寫的雙向鏈表就是借鑒的這里,如果邏輯不清楚,可以去看一下雙向鏈表那一篇文章
(insert)
在這里插入圖片描述

 iterator insert(iterator pos ,const T&x){node* cur = pos._node;node* prev = cur->_prev;node* newnode = new node(x);newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev = newnode;return newnode;}

(earse)
在這里插入圖片描述

 iterator erase(iterator pos){assert(pos != end());node* cur = pos._node;node* prev = cur->_prev;node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;return next;}

這里insert函數迭代器不會失效,而earse函數迭代器會失效,最好earse完,給迭代器傳下一個位置的地址。


析構函數

 void clear(){ iterator it = begin();while (it != end()){it = earse(it);//釋放完一個結點,返回下一個結點地址}}~list(){clear();//完成后只剩頭節點delete _head;//釋放頭節點_head = nullptr;//防止野指針cout<<"析構完成“<<endl;}

析構測試

	 void test8(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}res.~list();}

在這里插入圖片描述


push_front函數,pop_back()函數,pop_front()函數

因為實現了insert和earse,所以這三個就簡單了。

 void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}

注意這里的end()是最后一個數據的下一個位置,所以要先–
測試頭插

 void test6(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.push_front(1000);list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}

在這里插入圖片描述
測試頭刪和尾刪

void test7(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.pop_front();res.pop_back();list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}

在這里插入圖片描述
測試這三個間接測試了insert和erase


源碼展示

list.h

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zjw
{template<class T>struct listnode{listnode<T>* _next;listnode<T>* _prev;T _data;listnode(const T& x = T()):_prev(nullptr),_next(nullptr),_data(x){}};template<class T ,class res,class ptr>struct _list_iterator{ typedef    listnode <T>  node;typedef _list_iterator<T,res,ptr> self;node* _node;_list_iterator(node* n):_node(n){}self& operator++(){ _node= _node->_next;return * this;}self& operator--(){_node = _node->_prev;return * this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator !=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}res  operator*(){return _node->_data;}ptr  operator->(){return &_node->_data;}};template <class T>class list{typedef    listnode <T>  node;public:typedef _list_iterator<T,T&,T*>  iterator;typedef _list_iterator<T,const T&,const T*>  const_iterator;list(){empty_init();}void empty_init(){_head = new node();_head->_prev = _head;_head->_next = _head;}iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator  end() const{return _head;}iterator erase(iterator pos){assert(pos != end());node* cur = pos._node;node* prev = cur->_prev;node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;return next;}void clear(){ iterator it = begin();while (it != end()){it=erase(it);}}~list(){clear();delete _head;_head = nullptr;cout << "析構完成" << endl;}list(const list<T>& it){empty_init();for (auto e : it){push_back(e);}}void push_back(const T&x){node* newnode = new node(x);node* tail = _head->_prev;newnode->_next = _head;newnode->_prev = tail;tail->_next = newnode;_head->_prev = newnode;}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void swap(list<T>& tmp){std::swap(_head, tmp._head);}list<T>& operator=(list<T>it){swap(it);return *this;}iterator insert(iterator pos ,const T&x){node* cur = pos._node;node* prev = cur->_prev;node* newnode = new node(x);newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev = newnode;return newnode;}private :node* _head;};struct AA{int a1;int a2;AA(int _a1 = 0, int _a2 = 0):a1(_a1), a2(_a2){}};void print_list(const list<AA>it){list<AA>::const_iterator res =it.begin();while (res!=it.end()){cout << res.operator->()->a1 << ":" << res->a2 << endl;res++;}}/* void test1(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout <<*it << " ";it++;}}*///void test2()//{// list<int>res;// res.push_back(1);// res.push_back(2);// res.push_back(3);// res.push_back(4);// print_list(res);////////////}/* void test3(){list<AA>res; res.push_back(AA(1,1));res.push_back(AA(2,2));res.push_back(AA(3, 3));res.push_back(AA(4, 4));print_list(res);}*//* void test4(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret = res;list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}*//* void test5(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret(res);list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}*//* void test6(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.push_front(1000);list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}*//* void test7(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.pop_front();res.pop_back();list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}*/void test8(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}res.~list();}}

.cpp

#include"list.h"
int main()
{zjw::test8();}

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

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

相關文章

高維中介數據: 聯合顯著性(JS)檢驗法

摘要 中介分析在流行病學和臨床試驗中越來越受到關注。在現有的中介分析方法中&#xff0c;流行的聯合顯著性&#xff08;JS&#xff09;檢驗會產生過于保守的 I 類錯誤率&#xff0c;因此功效較低。但是&#xff0c;如果在使用 JS 測試高維中介假設時&#xff0c;可以準確控制…

人力資源(E-HR)應用架構的設計與實踐

當談到人力資源管理時&#xff0c;電子人力資源&#xff08;E-HR&#xff09;系統已經成為現代企業不可或缺的組成部分。E-HR系統的設計與實踐對于提高組織的人力資源管理效率和員工體驗至關重要。本文將探討E-HR應用架構的設計與實踐&#xff0c;以及如何借助信息技術優化人力…

docker清理閑置鏡像郵件發送

腳本名稱 DockerImage_Clear.sh腳本內容 #!/bin/bash # 清除閑置的docker鏡像 #docker image prune -a -f # 列出可清理的docker鏡像 /usr/local/bin/docker images | grep "<none>" # 列出可清理的docker鏡像數量 /usr/local/bin/docker images | grep …

怎么使用Pyecharts庫對淘寶數據進行可視化展示

目錄 一、準備工作 二、數據預處理 三、使用Pyecharts進行可視化展示 柱狀圖展示銷量和評價數 散點圖展示價格與銷量關系 詞云圖展示商品標題關鍵詞 四、總結與建議 在當今的大數據時代&#xff0c;數據可視化已經成為了一個非常重要的技能。Pyecharts是一個基于Python的…

NIO群聊系統的實現

一、前言 通過NIO編寫簡單版聊天室&#xff0c;客戶端通過控制臺輸入發送消息到其他客戶端。注意&#xff1a;并未處理粘包半包問題。 二、邏輯簡述 服務器&#xff1a; 1&#xff09;創建服務器NIO通道&#xff0c;綁定端口并啟動服務器 2&#xff09;開啟非阻塞模式 3&…

C++ //練習 10.24 給定一個string,使用bind和check_size在一個int的vector中查找第一個大于string長度的值。

C Primer&#xff08;第5版&#xff09; 練習 10.24 練習 10.24 給定一個string&#xff0c;使用bind和check_size在一個int的vector中查找第一個大于string長度的值。。 環境&#xff1a;Linux Ubuntu&#xff08;云服務器&#xff09; 工具&#xff1a;vim 代碼塊 /*****…

Altium Designer 22焊接輔助工具 Interactivehtmlbom 插件使用教程

目錄 AD22 由Interactivehtmlbom 插件生成的焊接輔助圖&#xff0c;交互方式很多&#xff0c;十分方便的為我們提供便利。 介紹安裝教程&#xff1a; 前去這個網站 Interactivehtmlbom 插件&#xff0c;單擊下載zip 下載完成后找個地方解壓&#xff0c;雙擊Initablelize.bat文…

河道水庫雨水情自動測報系統

隨著科學技術的不斷進步&#xff0c;以及城市化進程的影響&#xff0c;水庫的管理變得更加復雜&#xff0c;要實現城市水庫的精細化管理&#xff0c;必須借助先進的信息技術手段為支撐&#xff0c;實現對三防、水資源、供水安全的實時監控&#xff0c;優化管理模式和創新管理手…

餐飲廢水處理設備定制廠家

諸城市鑫淼環保小編帶大家了解一下餐飲廢水處理設備定制廠家 1.餐飲廢水問題 餐飲業是重要的經濟領域&#xff0c;但其廢水排放帶來的環境問題不容忽視。餐飲廢水含有高濃度的有機物、油脂、殘渣等&#xff0c;若未經處理直接排放&#xff0c;會嚴重污染水源&#xff0c;危害環…

Matlab 機器人工具箱 例程:運動學+動力學+路徑規劃+可視化

文章目錄 1 創建機器人2 機器人顯示3 機器人示教4 機器人路徑規劃&#xff1a;給定關節角路徑5 機器人路徑規劃&#xff1a;給定末端位姿&#xff0c;求關節角路徑6 工作空間可視化參考鏈接 1 創建機器人 clc;clear;close all; deg pi/180;L1 Revolute(d, 0, a, 0, alpha, 0,…

【Python】快速入門Python一天學完基礎語法

文章目錄 前言1. HelloWorld2. 變量與數據類型2.1 變量2.2 數據類型2.2.1 String 字符串類型2.2.2 基本類型轉換2.2.2 元組2.2.3 字典2.2.4 拆包 2.3 運算2.3.1 雙除號/雙乘號2.3.2 常見運算函數舉例2.3.3 布爾運算 3. 控制流程3.1 if-else 語句3.2 while 循環3.3 for 循環 4. …

子線程如何獲取Request

子線程獲取Request 有時候在進行業務處理時對于一些對于業務不那么重要且對于返回結果無關的情況會開啟一個新的線程進行處理&#xff0c;但是在開啟新線程進行處理時發現無法從RequestContextHolder中獲取到當前的請求&#xff0c;取出來是null 這是因為RequestContextHolder中…

逆變器專題(14)-弱電網下的LCL逆變器控制以及諧振峰問題(1)

相應仿真原件請移步資源下載 LCL濾波器 LCL濾波器因其本身為一個二階系統&#xff0c;其本身就會引發諧振&#xff0c;導致相應諧振頻率處的增益得到放大&#xff0c;進而產生諧波等問題&#xff1b;另一方面&#xff0c;在弱電網下&#xff0c;逆變器會與電網阻抗發生耦合&am…

ARM總結and復習

安裝交叉編譯工具鏈 a. 為什么安裝 因為arm公司的指令集在不斷迭代升級&#xff0c;指令集日益增多,而架構是基于指令集研發的&#xff0c;所以架構不一樣&#xff0c;指令集也不一樣 eg:arm架構使用的是arm指令集 x86架構使用的是x86指令集 而我們日常開發環境中linux的架構…

重載(Overload)和重寫(Override)的區別。重載的方法能否根據返回類型進行區分?

大家好我是蘇麟 , 今天開始又一個專欄開始了(又一個坑 哈哈) . 重載&#xff08;Overload&#xff09;和重寫&#xff08;Override&#xff09;的區別。重載的方法能否根據返回類型進行區分&#xff1f; 方法的重載和重寫都是實現多態的方式&#xff0c;區別在于前者實現的是編…

Java進階-測試方法

來學習一下軟件測試相關的方法&#xff0c;了解一下黑盒測試和白盒測試&#xff0c;以及后面要用到的JUnit單元測試。JUnit單元測試也屬于白盒測試&#xff0c;這次內容較少且相對簡單。 一、軟件測試方法 1、黑盒測試 不需要寫代碼&#xff0c;給輸入值&#xff0c;看程序…

分付在哪些商戶可以使用消費,微信分付怎么提取出來到余額上面來?

分付是一款信用支付產品&#xff0c;用戶可以使用分付進行線上線下的消費支付。下面是使用分付的一些方法&#xff1a; - 開通分付&#xff1a;在微信中搜索并開通分付服務&#xff0c;按照提示完成實名認證和綁定銀行卡等操作。 - 線上支付&#xff1a;在支持分付的線上商戶…

【Web - 框架 - Vue】隨筆 - 通過CDN的方式使用VUE 2.0和Element UI

通過CDN的方式使用VUE 2.0和Element UI - 快速上手 VUE 網址 https://cdn.bootcdn.net/ajax/libs/vue/2.7.16/vue.js源碼 https://download.csdn.net/download/HIGK_365/88815507測試 代碼 <!DOCTYPE html> <html lang"en"> <head><meta …

『大模型筆記』最大化大語言模型(LLM)的性能(來自OpenAI DevDay 會議)

最大化大語言模型(LLM)的性能(來自OpenAI DevDay 會議) 文章目錄 一. 內容介紹1.1. 優化的兩個方向(上下文優化和LLM優化)1.2. 提示工程:從哪里開始1.3. 檢索增強生成:拓展知識邊界1.4. 微調:專屬定制二. 參考文獻一. 內容介紹 簡述如何以可擴展的方式把大語言模型(LLMs)…

劍指offer》15--二進制中1的個數[C++]

1. 題目描述 輸入一個整數&#xff0c;輸出該數二進制表示中 1 的個數。 2. 解題思路 如果對負數直接右移&#xff0c;會導致最高位一直補1&#xff0c;最終變成0xFFFF死循環。 常規做法&#xff1a; 3. 代碼實現 #include<iostream> #include<vector> using…