波奇学C++:stl的list模拟实现

news2024/11/23 12:43:12

list是双向带头链表。所以迭代器end()相当于哨兵卫的头。

list不支持+和[]重载,原因在于list空间不是连续的,+和[]的代价比较大。

访问第n个节点,只能用for循环,++来实现

list<int> l;
l.push_back(0);
l.push_back(1);
l.push_back(2);
l.push_back(3);
auto li=l.begin();
//访问第3个节点
for(size_t i=0;i<3;i++)
{
    li++;
}

list的insert不会失效,但是erase会迭代器失效。

list是双向迭代器

迭代器可以简单分为:单向迭代器(forward)++,双向迭代器(bidirectional) ++/-- 随机迭代器(random acess)+/-/++/--

不同的数据结构的迭代器决定了可以使用不同的算法。其中随机迭代器代器的范围最广,可以用的算法最多。

std:sort只能是随机迭代器用,list不能使用,list也有自己的sort算法但是效率并不高。

list实现

大概思路先不考虑迭代器,链表分为两个类,一个类表示节点,另外一个类表示链表。

节点模板类

template<class T>
	struct list_node
	{
		list_node<T>* _next;
		list_node<T>* _prev;
		T _val;
		list_node(const T& val = T())
			:_next(nullptr)
			,_prev(nullptr)
			,_val(val)
		{

		}
	};

这里有个注意的点,模板类的类名不是类型,list_node只是类名,不是对应的自定义类型,所以是

list_node<T>* _next;而不是list_node* _next。

编译器优化 

拷贝构造写类名也可以

模拟实现的代码

namespace my_list
{
    template<class T> 
    struct list_node
    {

        list_node<T>* _prev;
        list_node<T>* _next;
        T _val;
        list_node(const T& val=T())
            :_next(nullptr)
            ,_prev(nullptr)
            ,_val(val)
        {}
    };
    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)
        {}
        Ref operator*()
        {
            return _node->_val;

        }
        self& operator++()
        {
            _node = _node->_next;
            return *this;
        }
        self& operator--()
        {
            _node = _node->_prev;
            return *this;
        }
        bool operator!=(const self& it)
        {
            return _node != it._node;
        }
        self operator++(int)
        {
            self tmp(*this);
            _node = _node->_next;
            return tmp;
        }
        Ptr operator->()
        {
            return &_node->_val;
        }
    };
    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;
        iterator begin()
        {
            return _head->_next; 
        }
        iterator end()
        {
            return _head;
        }
        const_iterator const_begin()
        {
            return _head->_next;
        }
        const_iterator const_end()
        {
            return _head;
        }
        void empty_init()
        {
            _head = new Node;
            _head->_next = _head;
            _head->_prev = _head;
        }
        list()
        {
            empty_init();
        }
        ~list()
        {
            clear();
            delete _head;
            _head = nullptr;
        }
        list(const list<T>& lt)
        {
            empty_init();

            for (auto& e : lt)
            {
                push_back(e);
            } 
        }
        void swap(list<T>& lt)
        {
            std::swap(_head, lt._head);
            std::swap(_size, lt._size);
        }
        list<T>& operator=(list<T> lt)
        {
            swap(lt);
            return *this;
        }
        ~list()
        {
            clear();
            delete _head;
            _head = nullptr;
        }
        void push_back(const T& x)
        {/*
            Node* tail =_head->_prev;
            Node* newnode = new Node(x);
            tail->_next = newnode;
            newnode->_prev = tail;
            newnode->_next = _head;
            _head->_prev = newnode;*/
            insert(end(), x);
        }
        void push_front(const T& x)
        {
            insert(begin(), x);
        }
        void pop_back()
        {
            erase(--end());
        }
        void pop_begin()
        {
            erase(begin());
        }
        iterator insert(iterator pos, const T& x)
        {
            Node* cur = pos._node;
            Node* prev = cur->_prev;
            Node* newnode = new Node(x);
            prev->_next = newnode;
            newnode->_next = cur;
            cur->_prev = newnode;
            newnode->_prev = prev;
            return newnode;
        }
        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);
            }
        }
        size_t size()
        {
            size_t sz = 0;
            iterator it = begin();
            while (it != end())
            {
                sz++;
            }
            return sz;
        }
    private:
        Node* _head;
        Node* _tail;
    };
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/914159.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营之JAVA|第三十五天|343. 整数拆分

今天是第 天刷leetcode&#xff0c;立个flag&#xff0c;打卡60天&#xff0c;如果做不到&#xff0c;完成一件评论区点赞最高的挑战。 算法挑战链接 343. 整数拆分https://leetcode.cn/problems/integer-break/ 第一想法 题目理解&#xff1a;将一个整数拆分为k个整数&…

python matlab 画坐标图

画一个坐标系&#xff0c;同时显示两条直线&#xff0c;效果图如下&#xff1a; 功能点&#xff1a; 同时显示两个纵坐标数据 显示图片名称 图片最大化保存 到本地 在图片某个位置显示字符信息 不同的线名称提示 代码如下&#xff1a; import matplotlib.pyplot as pltde…

学习左耳听风栏目90天——第七天 7/90(学习左耳朵耗子的工匠精神,对技术的热爱)【每个程序员都该知道的事】

每个程序员都该知道的事 每个程序员都应该要读的书每个搞计算机专业的学生应有的知识LinkedIn 高效的代码复查技巧编程语言和代码质量的研究报告 每个程序员都应该要读的书 每个搞计算机专业的学生应有的知识 LinkedIn 高效的代码复查技巧 编程语言和代码质量的研究报告

C++头文件和std命名空间

C 是在C语言的基础上开发的&#xff0c;早期的 C 还不完善&#xff0c;不支持命名空间&#xff0c;没有自己的编译器&#xff0c;而是将 C 代码翻译成C代码&#xff0c;再通过C编译器完成编译。 这个时候的 C 仍然在使用C语言的库&#xff0c;stdio.h、stdlib.h、string.h 等头…

CentOS7网络配置

本文是我从另外三个文章中整合而来&#xff0c;用于自存&#xff0c;如有侵权请联系我删除。 CentOS 7教程&#xff08;二&#xff09;-网络设置 - 知乎 (zhihu.com) VMware安装、Linux下CentOS7的配置及网络环境的配置&#xff08;最新版特别全&#xff09;_centos7 配置_Co…

田间气象站的优势与应用

在农业生产中&#xff0c;田间气象站是重要的气象监测工具&#xff0c;它能够对农田间的气象信息进行实时监测和记录&#xff0c;为农民伯伯提供农业生产科学依据。 田间气象站是由多个传感器共同组成&#xff0c;能够收集各项气象参数&#xff0c;包括我们常见的风速、风向、…

STM32--MPU6050与I2C外设

文章目录 前言MPU6050参数电路MPU6050框图 IIC外设框图 IIC的基本结构软件IIC实现MPU6050硬件IIC实现MPU6050 前言 在51单片机专栏中&#xff0c;用过I2C通信来进行实现AT24C02的数据存储&#xff1b; 里面介绍的是利用程序的编程来实现I2C的时序&#xff0c;进而实现AT24C02与…

关于android studio 几个简单的问题说明

自信是成功的第一步。——爱迪生 1. android studio 如何运行不同项目是否要更换不同的sdk 和 gradle 2.编译Gradle总是错误为什么 3.如何清理android studio 的缓存 4. 关于android Studio中的build 下面的rebuild project

『SEQ日志』在 .NET Core 中轻松集成 NLog 和 SEQ ,打造轻量级的分布式日志系统

&#x1f4e3;读完这篇文章里你能收获到 如何在Docker中部署 SEQ&#xff1a;介绍了如何创建和运行 SEQ 容器&#xff0c;给出了详细的执行操作如何使用 NLog 接入 .NET Core 应用程序的日志&#xff1a;详细介绍了 NLog 和 NLog.Seq 来配置和记录日志的步骤日志记录示例&…

判断三角形

int main() {int a 0;int b 0;int c 0;scanf("%d%d%d", &a, &b, &c);if ((ab>c)&&(ac>b)&&(bc>a)){if (a b && b c){printf("等边三角形\n");}else if ((a b && b ! c) || (a c && c…

企业的降本增益,从源头抓起——精细化管理每一条销售线索

存量经济时代&#xff0c;降本增效成为企业增长的重点抓手&#xff0c;也是企业自身数字化建设重要目标。 如何能让销售更珍惜线索&#xff1f;如何能让线索产生更快的转化&#xff1f;如何能让对的线索给到对的销售&#xff1f;如何能依托线索转化结果找到更有效的获客渠道&a…

【踩坑日记】STM32 USART 串口与 FreeRTOS 冲突

文章目录 问题描述问题出现的环境问题解决过程第一步第二步第三步第四步第五步第六步第七步第八步 后续验证一些思考类似的问题后记 问题描述 笔者使用 FreeRTOS 创建了两个任务&#xff0c;使两颗 LED 以不同频率闪烁&#xff0c;但是在加入串口 USART 部分代码后&#xff0c…

Shader 用到的数学函数总结及用法

在写shader相关的程序的时候往往需要用到 OpenGL内置的数学库&#xff0c;下面列举几个常用的函数用法和效果&#xff0c;下面的所有代码都是运行在shadertoy在线工具上的&#xff0c;推荐一个好用的数学工具desmosDesmos 目录&#xff1a; abs(x)step(edge,x)dot(uv1,uv2) …

MySQL双主架构、主从架构

为什么要对数据库做优化&#xff1f; MySQL官方说法&#xff1a; 单表2000万数据就达到瓶颈了。所以为了保证查询效率&#xff0c;要让每张表的大小得到控制。 MySQL主主架构 主数据库都负责增删改查。 比如有1000W的数据&#xff0c;有两个主数据库&#xff0c;就将数据分流给…

古巴勒索软件-CVE-2023-27532工具利用

黑莓捕获古巴勒索软件&#xff0c;其中一项工具有关CVE漏洞工具利用&#xff0c;利用有关CVE-2023-27532编号的漏洞利用工具进行投放。 MD5 9a3349f062130201a3dc16e78d5ab05d SHA-1 96e0a6a2aa12ed572fea9a1a858c903356bce1ab SHA-256 cf87a44c575d391df668123b05c207eef0…

代码随想录 (四)字符串

1.反转字符串 class Solution { public:void reverseString(vector<char>& s) {for (int i 0, j s.size() - 1; i < s.size()/2; i, j--) {swap(s[i],s[j]);}} };2.反转字符串II 直接用reverse&#xff08;是左闭右开的&#xff09; std::reverse 是 C 标准库中…

【2023深圳杯数学建模A题思路模型与代码分享】

2023深圳杯数学建模A题 A题 影响城市居民身体健康的因素分析解题思路第一问第二问第三问第四问 技术文档第一问完整代码写在最后 A题 影响城市居民身体健康的因素分析 以心脑血管疾病、糖尿病、恶性肿瘤以及慢性阻塞性肺病为代表的慢性非传染性疾病&#xff08;以下简称慢性病…

TCP性能机制

延迟应答 为什么有延迟应答 发送方如果长时间没有收到ACK应答&#xff0c;则会触发超时重传机制&#xff0c;重新发送数据包。但如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小&#xff0c;发送方一次只能发少量数据&#xff0c;效率较低。 举个例子理解一…

高性能服务器NodejsExpress快速构建Web

目录 1 Express基本使用1.1 托管静态资源 2 Express 路由3 Express 中间件3.1 全局中间件3.2 局部中间件3.3 中间件分类 4 CORS 跨域资源共享4.1 cors 中间件解决跨域4.2 CORS4.3 CORS 常见响应头4.4 CORS 请求分类 1 Express基本使用 官网传送门(opens new window) 基于 Node.…

简单计算器的实现(含转移表实现)

文章目录 计算器的一般实现使⽤函数指针数组的实现&#xff08;转移表&#xff09; 计算器的一般实现 通过函数的调用&#xff0c;实现加减乘除 # define _CRT_SECURE_NO_WARNINGS#include<stdio.h>int Add(int x, int y) {return x y; }int Sub(int x, int y) {retur…