STL——list模拟实现

ops/2024/10/20 6:36:20/

一、模拟实现源码

#pragma oncenamespace sjx
{template <typename T>struct __list_node{__list_node<T>* _next;__list_node<T>* _prev;T _data;__list_node(const T& val = T()) :_data(val), _next(nullptr), _prev(nullptr){}};template <typename T, typename Ref, typename Ptr>struct __list_iterator{typedef __list_node<T> node;typedef __list_node<T>* node_pointer;typedef __list_iterator<T, Ref, Ptr> self;typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;node_pointer _pnode;__list_iterator(const node_pointer& val = nullptr) :_pnode(val) {}__list_iterator(const iterator& it) :_pnode(it._pnode) {}Ref operator*(){return _pnode->_data;}Ptr operator->(){return &(_pnode->_data);}bool operator!=(const self& val) const{return _pnode != val._pnode;}bool operator==(const self& val) const{return _pnode == val._pnode;}self& operator++(){_pnode = _pnode->_next;return *this;}self operator++(int){self tmp(_pnode);_pnode = _pnode->_next;return tmp;}self& operator--(){_pnode = _pnode->_prev;return *this;}self operator--(int){self tmp(_pnode);_pnode = _pnode->_prev;return tmp;}};template <typename T>class list{public:typedef __list_node<T> node;typedef __list_node<T>* node_pointer;typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;list(){empty_initialize();}template <typename InputIterator>list(InputIterator first, InputIterator last){empty_initialize();while (first != last){push_back(*first);++first;}}list(const list& other){empty_initialize();list<T> tmp(other.begin(), other.end());swap(tmp);}~list(){clear();delete _head;}list<T>& operator=(list<T> other){empty_initialize();swap(other);return *this;}// Element accessT& front(){assert(!empty());return _head->_next->_data;}const T& front() const{assert(!empty());return _head->_next->_data;}T& back(){assert(!empty());return _head->_prev->_data;}const T& back() const{assert(!empty());return _head->_prev->_data;}// Iteratorsiterator begin(){return _head->_next;}const_iterator begin() const{return _head->_next;}iterator end(){return _head;}const_iterator end() const{return _head;}// Capacitybool empty() const{return _head->_next == _head;}size_t size() const{size_t i = 0;node_pointer cur = _head->_next;while (cur != _head){++i;cur = cur->_next;}return i;}// Modifiersvoid clear(){node_pointer cur = _head->_next;while (cur != _head){node_pointer tmp = cur->_next;delete cur;cur = tmp;}_head->_next = _head;_head->_prev = _head;}iterator insert(const_iterator pos, const T& val){node_pointer cur = new node(val);node_pointer tail = pos._pnode;node_pointer head = tail->_prev;head->_next = cur;cur->_next = tail;tail->_prev = cur;cur->_prev = head;return cur;}iterator insert(const_iterator pos, size_t count, const T& val){for (size_t i = 0; i < count; ++i){pos = insert(pos, val);}return pos._pnode;}template <typename InputIterator>iterator insert(const_iterator pos, InputIterator first, InputIterator last){node_pointer head = pos._pnode;if (first != last){head = insert(pos, *first)._pnode;++first;}while (first != last){insert(pos, *first);++first;}return head;}iterator erase(const_iterator pos){node_pointer tmp = pos._pnode;if (pos != end()){node_pointer del = tmp;tmp = tmp->_next;del->_prev->_next = del->_next;del->_next->_prev = del->_prev;delete del;}return tmp;}iterator erase(const_iterator first, const_iterator last){while (first != last){first = erase(first);}return last._pnode;}void push_back(const T& val){node_pointer tmp = new node(val);node_pointer tail = _head->_prev;tail->_next = tmp;tmp->_next = _head;_head->_prev = tmp;tmp->_prev = tail;}void pop_back(){erase(--end());}void push_front(const T& val){insert(begin(), val);}void pop_front(){erase(begin());}void swap(list<T>& val){std::swap(_head, val._head);}protected:void empty_initialize(){_head = new node;_head->_next = _head;_head->_prev = _head;}private:node_pointer _head;};
}

二、重难点——迭代器实现

list的迭代器不同于vector,vector的迭代器用指针就可以实现大部分功能,但是list的迭代器要实现++,不再是单纯数值上的加减,而是要让迭代器指向当前结点的next。

因此,需要将list的迭代器封装成一个类__list_iterator。通过运算符重载,来改变迭代器运算的效果。

需要注意的是__list_iterator还有另外两个模板参数,Ref和Ptr。

对于const_iterator,它与普通的iterator的区别就是它里面的内容不允许被修改,但是本身依旧可以进行++或者--等操作,其区别之一就在于对迭代器的解引用,一个的返回值可以被修改,一个不可以,因此我们引入了一个模板参数Ref,对于普通的迭代器,它被设置为T&,而对于const迭代器,它被设置为const T&。

对于模板参数Ptr,需要应对以下情况:

#include <iostream>
#include <assert.h>
#include "my_list.h"
struct Data
{int _year;int _month;int _day;Data(int year = 2000, int month = 1, int day = 1):_year(year), _month(month), _day(day){}
};int main()
{// 如果存储的对象是自定义类型,且要访问其中的数据sjx::list<Data> l1;l1.push_back(Data());sjx::list<Data>::iterator it = l1.begin();// 使用 * 访问std::cout << (*it)._year << " " << (*it)._month << " " << (*it)._day << std::endl;// 使用 operator->std::cout << it.operator->()->_year << " " << it.operator->()->_month << " " << it.operator->()->_day << std::endl;// 为了可读性,一般我们省略了一个 ->std::cout << it->_year << " " << it->_month << " " << it->_day << std::endl;return 0;
}

以上三种输出方式实际上是等价的。


http://www.ppmy.cn/ops/56062.html

相关文章

linux下删除当前路径下的所有文件夹但保留文件

打开终端&#xff0c;输入&#xff0c; find . -mindepth 1 -maxdepth 1 -type d -exec rm -r {} 解释&#xff1a; find是查找文件和文件夹的命令。.表示当前路径。-mindepth 1表示最小搜索深度为1&#xff0c;这样不会包括当前目录。-maxdepth 1表示最大搜索深度为1&#x…

算法整理——【贪心算法练习(2)】

我们继续对贪心算法进行练习&#xff0c;积累题目经验。 一、根据身高重建队列 题目为406. 根据身高重建队列 - 力扣&#xff08;LeetCode&#xff09;&#xff0c;假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺…

git上传文件

git init git add . git commit -m " " git remote add origin 仓库的地址 git push -u origin master 如果出现以下问题 可以用这一句强制上传 git push -f origin master

golang 模板引擎常用语法

golang 模板常用语法 1、变量赋值 Action里可以初始化一个变量来捕获管道的执行结果。初始化语法如下&#xff1a; 其中$variable是变量的名字。声明变量的action不会产生任何输出。 {{$variable : pipeline}}福利彩蛋&#xff1a;没有好玩的 API 接口&#xff1f;上百款免费接…

字节码编程javassist之打印方法耗时和入参

写在前面 本文看下如何实现打印方法耗时和入参。 1&#xff1a;程序 需要增强的类&#xff1a; public class ApiTest1 {public Integer strToInt(String str01, String str02) {return Integer.parseInt(str01);}}插桩类 package com.dahuyou.javassist.huohuo.aa;import…

LeetCode377. 组合总和 Ⅳ

为何先遍历背包、后遍历物品&#xff0c;得到的是排列数呢&#xff1f; 以本题为例&#xff1a;&#xff08;背包容量用j表示&#xff0c;选择的物品下标用i表示&#xff09; j为1时&#xff1a; i0&#xff0c;表示把nums[0]放置在该集合的最后一个元素的位置 那么所得集合为…

2024年最适合高级网工的11款Linux

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 你们好&#xff0c;我的网工朋友。 Linux作为一个免费且开源的操作系统&#xff0c;随着时间的推移催生了多个发行版&#xff0c;并且得到了庞大…

【EI稳定检索】第五届大数据、人工智能与软件工程国际研讨会(ICBASE 2024)

>>>【独立出版&#xff0c;Ei稳定检索】<<< 第五届大数据、人工智能与软件工程国际研讨会&#xff08;ICBASE 2024&#xff09; 2024年09月20-22日 | 中国温州 一轮截稿时间&#xff1a;2024年7月8日 二轮截稿时间&#xff1a;2024年8月5日 大会简介 *会议…