【STL容器】list

文章目录

  • 一、list定义
  • 二、list的迭代器
  • 三、list的元素操作
  • 四,list的优缺点


一、list定义

list本质是一个双向带头循环链表

在这里插入图片描述

template<class T>
struct list_node
{list_node* prev;T val;list_node* next;
};template<class T>
class list
{typedef list_node<T> node; 
private:node* head;
};

二、list的迭代器

不同于vector的迭代器,list的迭代器是一个类,原因是list是链式空间,普通指针的++,–不能访问到正确的地址,因此需要运算符重载++,–等。

template<class T, class ref, class ptr>
struct list_iterator
{
private:typedef list_node<T> node;typedef list_iterator<T, ref, ptr> self;
public:node* _cur;
};

这里有一个重点,模板参数ref,ptr是干什么的?
在list类中是这样定义iterator
typedef list_iterator<T, T&, T*> iterator;
typedef list_iterator<T, const T&, const T*> const_iterator;
这表示 ref传的是T的引用,ptr传的是T的指针,这不是多此一举吗?
但偏偏list的源码也是这样的。
在这里插入图片描述
这是为什么呢?
我们将list_iterator封装为一个类,主要是想重载它的++,–等运算符,以便正确使用iterator;
下面这是list_literator的前置++,它的返回值应该是 list_iterator<T>&,但如果我使用的是const_iterator,它的返回值应该是const list_iterator<T>&,二者的区别仅仅只是返回值不同,但仅仅返回值不同,不能构成函数重载。这样仅仅想靠一个类list_iterator是不行的,那就只能再写一个类const_list_iterator.

返回值 operator++()
{_cur = _cur->next;return *this;
}

但如果传参时,T& | const T& 作为一个参数传递,就可以只写list_iterator,来完成iterator 和 const_iterator.虽然本质上还是创建了2个类,但创建的工作由编译器解决,我们只用手写一个类就够了。

template<class T, class ref, class ptr>struct list_iterator{private:typedef list_node<T> node;typedef list_iterator<T, ref, ptr> self;//iterator 则 ref = T&//const_iterator 则 ref = const T&public://成员变量node* _cur = nullptr;//迭代器:构造,++, *list_iterator(node* it = nullptr){_cur = it;}self& operator++()    {_cur = _cur->_next;return *this;}self& operator++(int){self tmp(*this);_cur = _cur->_next;return tmp;}ref operator*() const{return _cur->_val;}};

ptr同理,它主要服务operator->()

ptr operator->() const
{return &(_cur->_val);
}

注:这里有个小知识,operator的返回值可能让人感到疑惑。

在这里插入图片描述
C++ 中的 operator-> 被用于重载类的成员访问操作符 ->。这个操作符通常用于访问类的成员函数和成员变量,而且在许多情况下,它应该返回一个指向类的成员的指针。这是因为 -> 操作符通常用于访问类的成员,而类的成员可以是函数或变量。


三、list的元素操作

list的插入删除,本质就是双向带头链表的插入删除,下面给出一些简单的模拟实现。

list(const T& t = T())
{head = new node;node* tmp = new node;tmp->_val = t;tmp->_next = head;tmp->_prev = head;head->_next = tmp;head->_prev = tmp;++_size;
}
list(const list<T>& t)
{for (auto& e : t){push_back(e);}
}
~list()
{iterator it = begin();while (it != end()){it = erase(it);}delete head;head = nullptr;
}
void swap(list<T>& lt)
{std::swap(head, lt.head);std::swap(size, lt.head);
}
list<T>& operator=(list<T> lt)
{swap(lt);
}
//iterator
iterator begin()
{return iterator(head->_next);
}
iterator end()
{return iterator(head);
}
//capacity
size_t size()
{return _size;
}
//modify
void push_back(const T& t = T())
{insert(end(), t);
}
void push_front(const T& t = T())
{insert(begin(), t);
}
void insert(iterator pos, const T& t)
{node* cur = pos._cur;node* prev = cur->_prev;node* tmp = new node;tmp->_val = t;tmp->_prev = prev;tmp->_next = cur;prev->_next = tmp;cur->_prev = tmp;++_size;
}
void pop_back()
{iterator it(head->_prev);erase(it);
}
void pop_front()
{erase(begin());
}
iterator erase(iterator pos)
{node* cur = pos._cur;node* prev = cur->_prev;node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;return iterator(next);
}

list在使用时,一定要注意迭代器失效的问题。

四,list的优缺点

STL(标准模板库)中的 std::list 是一个双向链表(doubly linked list)的实现,它具有一些优点和缺点,适用于不同的使用情况。

优点:

  1. 插入和删除效率高: std::list 对于插入和删除操作非常高效,因为在双向链表中,插入和删除元素只需要改变相邻节点的指针,而不需要移动其他元素。

  2. 稳定的迭代器: 在插入和删除元素时,std::list 保持了迭代器的有效性。这意味着在遍历列表时进行插入或删除操作不会导致迭代器失效,这在其他容器中(如 std::vector)是不成立的。

  3. 内存管理灵活: 由于链表的节点可以分散存储在内存中,std::list 具有一定的内存分配灵活性。这可以避免动态数组(如 std::vector)可能会发生的重新分配和复制开销。

缺点:

  1. 随机访问效率低: std::list 不支持常数时间的随机访问,因为要遍历链表需要 O(n) 的时间复杂度。如果需要频繁的随机访问元素,std::vector 更适合。

  2. 性能较差的缓存局部性: 由于链表节点在内存中是离散分布的,因此对于大型数据集,std::list 的性能可能受到缓存局部性的影响,而数组式容器更有可能利用好缓存。

  3. 不支持随机访问和下标访问: std::list 不支持像数组那样的随机访问或下标访问,这限制了其在某些应用中的使用。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何打造可视化警务巡防通信解决方案

近年来&#xff0c;科学技术飞速发展&#xff0c;给予了犯罪分子可乘之机。当面临专业化的犯罪分子、高科技的犯罪手段&#xff0c;传统警务模式似乎不能满足警方打击犯罪的需要&#xff0c;因此当今公安工作迫切需要构建智能化、系统化、信息化的警务通信管理模式。 警务人员…

python 第一次作业

1.使用turtle换一个五环 2.设计这样一个程序&#xff1a;输入一个数字 判断它是不是一个质数 使用turtle换一个五环&#xff1a; >>> import turtle #导入模块 >>> turtle.width(10) #设置圆圈宽度 >>> turtle.color("blue&qu…

JDK10特性

文章目录 JAVA10概述语法层次的变化局部变量的类型推断不能使用类型推断的场景变量的声明初始值nulllambda表达式方法引用为数组静态初始化成员变量不能使用其他不可以的场景 API层次的变化集合的copyOf方法 总结 JAVA10概述 2018年3月21日&#xff0c;Oracle官方宣布JAVA10正…

HTML整站规划与规范

文章目录 命名规则命名命名书写 包含样式规范样式重置样式引入页面结构页面宽度页面高度与背景页面设计 网址图标 命名规则 命名 根据每块元素的主题、功能、页面上的位置命名&#xff0c;便于后期更改与维护。 另外&#xff1a;如果所有样式放在同一文件下&#xff0c;可以给…

BUUCTF:[GYCTF2020]FlaskApp

Flask的网站&#xff0c;这里的功能是Base64编码解码&#xff0c;并输出 并且是存在SSTI的 /hint 提示PIN码 既然提示PIN&#xff0c;那应该是开启了Debug模式的&#xff0c;解密栏那里随便输入点什么报错看看&#xff0c;直接报错了&#xff0c;并且该Flask开启了Debug模式&am…

qt自定义可删除标签控件、自适应布局

自定义标签&#xff0c;支持删除、设置/获取数据、自适应布局操作。 如图&#xff0c;可点击删除按钮操作、拖拽窗口自适应&#xff1b; 代码参考

21天学会C++:Day11----运算符重载

CSDN的uu们&#xff0c;大家好。这里是C入门的第十一讲。 座右铭&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a;C专题 目录 1. 知识引入 2. 运算符重载 2.1 operator<() 2.2 operator() 2.3 o…

Vue的详细教程--基础语法【上】

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Vue的相关操作吧 一.插值 1.文本 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>插值</title>&l…

python爬虫爬取电影数据并做可视化

思路&#xff1a; 1、发送请求&#xff0c;解析html里面的数据 2、保存到csv文件 3、数据处理 4、数据可视化 需要用到的库&#xff1a; import requests,csv #请求库和保存库 import pandas as pd #读取csv文件以及操作数据 from lxml import etree #解析html库 from …

element 搜索框静态查询

效果图 代码块 <template><div><!-- 1.产品搜索 --><div class"header"><div class"from"><el-form :inline"true" :model"formInline" class"demo-form-inline"><el-form-item l…

Vue复选框批量删除示例

Vue复选框批量删除 通过使用v-model指令绑定单个复选框 例如<input type"checkbox" id"checkbox" v-model"checked"> 而本次我们要做的示例大致是这样的&#xff0c;首先可以增加内容&#xff0c;然后通过勾选来进行单独或者批量删除&…

[计算机入门] 电源选项设置

3.10 电源选项设置 有时候我们的电脑一段时间没有用&#xff0c;会自己关掉屏幕或者直接睡眠&#xff0c;这是电源选项没有设置好导致的。 1、打开控制面板&#xff0c;打开其中的电源选项 2、点击左侧上方的选择关闭显示器的时间 3、进入到编辑计划设置界面&#xff0c;在…

【Vue】MVVM模型还没懂嘛

hello&#xff0c;我是小索奇&#xff0c;精心制作的Vue教程持续更新哈&#xff0c;想要学习&巩固&避坑就一起学习叭~ MVVM 模型 Vue虽然没有完全遵循MVVM模型&#xff0c;但Vue的设计也收到了它的启发在文档中也会使用VM&#xff08;ViewModel的缩写&#xff09;这个变…

安防电源芯片有哪些-42v转5v芯片

安防电源芯片有多种种类和型号&#xff0c;以下是一些常见的安防电源芯片&#xff1a; 1. 电源管理芯片&#xff08;Power Management IC&#xff0c;PMIC&#xff09;&#xff1a;这些芯片用于管理和控制安防系统的电源供应&#xff0c;包括电压调整、电流控制、电池管理等功…

全网多种方法解决idea中报出的Cannot find declaration to go to的问题

文章目录 1. 发现错误2. 分析问题3. 解决错误4. 解决该错误的其他方法4.1 其他方法14.2 其他方法24.3 其他方法34.4 其他方法44.5 解决方法54.6 解决方法6 5. 文章总结 1. 发现错误 今早下载一新项目&#xff0c;打开之后&#xff0c;点击对应的代码时&#xff0c;却报出如下错…

thrift的简单使用

写在前面 本文一起看下一种由facebook出品的rpc框架thrift。 源码 。 1&#xff1a;开发步骤 1:编写thrift idl文件 2&#xff1a;根据thrift idl文件生成java模板代码 3&#xff1a;继承模板代码的*.Iface接口给出server的具体服务实现 4&#xff1a;使用模板的HelloWorldSe…

Leetcode: 645.错误的集合 题解【超详细】

题目 集合 s 包含从 1 到 n 的整数。不幸的是&#xff0c;因为数据错误&#xff0c;导致集合里面某一个数字复制了成了集合里面的另外一个数字的值&#xff0c;导致集合 丢失了一个数字 并且 有一个数字重复 。 给定一个数组 nums 代表了集合 S 发生错误后的结果。 请你找出重复…

Redis模块一:缓存简介

目录 缓存的定义 应用 生活案例 程序中的缓存 缓存优点 缓存的定义 缓存是⼀个高速数据交换的存储器&#xff0c;使用它可以快速的访问和操作数据。 应用 1.CPU缓存&#xff1a;CPU缓存是位于CPU和内存之间的临时存储器&#xff0c;它的容量通常远小于内存&#xff0…

微信小程序云开发手搓微标提示,逻辑思路记录及代码实现

目录 写前小叙 功能需求背景 首页js的逻辑思路第一部分 发布公告js逻辑 首页js显示“新”公告思路实现 首页js关闭“新”公告思路实现 管理员“已阅读”js逻辑 首页js显示“新”邮件思路实现 首页js关闭“新”邮件思路实现 写前小叙 今儿凌晨&#xff0c;我又是一个人…

综合管廊安全监测,助力市政管廊智能化管理

综合管廊是一种集管线维护、建设、管理于一体的地下综合通道&#xff0c;可以将电力、通讯、燃气、供热、供水等工程管线集于一体&#xff0c;综合管廊对于城市建设具有重要意义&#xff0c;可以防止管线破裂&#xff0c;杜绝反复开挖路面&#xff0c;有效缓解交通拥堵&#xf…