C++STL之list

目录

1.list的使用

2.list iterator的使用 

3.list的常用接口 

4.list的迭代器失效 

5.list的模拟实现 

6.list的反向迭代器 

7.list与vector的对比


1.list的使用

构造函数
接口说明
list (size_type n, const value_type& val =
value_type())
构造的 list 中包含 n 个值为 val
元素
list()
构造空的list
list (const list& x)
拷贝构造函数
list (InputIterator first, InputIterator last
[first, last) 区间中的元素构造
list

2.list iterator的使用 

可以将迭代器理解成一个指针,该指针指向 list 中的某个节点
函数声
接口说明
begin +
end
返回第一个元素的迭代器 + 返回最后一个元素下一个位置的迭代器
rbegin
+ rend
返回第一个元素的 reverse_iterator, end 位置 返回最后一个元素下一个位
置的 reverse_iterator, begin 位置

【注意】
1. begin end 为正向迭代器,对迭代器执行 ++ 操作,迭代器向后移动
2. rbegin(end) rend(begin) 为反向迭代器,对迭代器执行 ++ 操作,迭代器向前移动

 

3.list的常用接口 

函数声明
接口说明
empty
检测 list 是否为空,是返回 true ,否则返回 false
size
返回list中有效节点的个数
front
返回list的第一个节点中值的引用
back
返回list的最后一个节点中值的引用
push_front
list首元素前插入值为val的元素
pop_front
删除 list 中第一个元素
push_back
list尾部插入值为val的元素
pop_back
删除list中最后一个元素
insert
list position 位置中插入值为val的元素
erase
删除list position位置的元素
swap
交换两个 list 中的元素
clear
清空list中的有效元素
4.list的迭代器失效 
前面说过,此处大家可将迭代器暂时理解成类似于指针, 迭代器失效即迭代器所指向的节点的无
效,即该节点被删除了 。因为 list 的底层结构为带头结点的双向循环链表 ,因此 list 中进行插入
时是不会导致 list 的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭
代器,其他迭代器不会受到影响

 

void TestListIterator1()
{
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
list<int> l(array, array+sizeof(array)/sizeof(array[0]));
auto it = l.begin();
while (it != l.end())
{
// erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给
其赋值
l.erase(it);
++it;
}
}
// 改正
void TestListIterator()
{
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
list<int> l(array, array+sizeof(array)/sizeof(array[0]));
auto it = l.begin();
while (it != l.end())
{
l.erase(it++); // it = l.erase(it);
}
}

 

5.list的模拟实现 
#pragma once
#include<iostream>namespace bit
{template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& data = T()):_data(data), _next(nullptr), _prev(nullptr){}};// const_iteratortemplate<class T>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T> Self;Node* _node;list_iterator(Node* node):_node(node){}T& operator*(){return _node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}bool operator!=(const Self& s) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}};template<class T>class list{typedef list_node<T> Node;public:typedef list_iterator<T> iterator;iterator begin(){/*	iterator it(_head->_next);return it;*///return iterator(_head->_next);return _head->_next;}iterator end(){return _head;}list(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}void push_back(const T& x){/*Node* newnode = new Node(x);Node* tail = _head->_prev;tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;++_size;*/insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);// prev newnode curnewnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;prev->_next = newnode;++_size;}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void erase(iterator pos){assert(pos != end());Node* prev = pos._node->_prev;Node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;--_size;}size_t size() const{return _size;}bool empty() const{return _size == 0;}private:Node* _head;size_t _size;};void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){std::cout << *it << " ";++it;}std::cout << std::endl;}
}

 

6.list的反向迭代器 
通过前面例子知道,反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++
因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对
正向迭代器的接口进行包装即可。
template<class Iterator>
class ReverseListIterator
{
// 注意:此处typename的作用是明确告诉编译器,Ref是Iterator类中的类型,而不是静态
成员变量
// 否则编译器编译时就不知道Ref是Iterator中的类型还是静态成员变量
// 因为静态成员变量也是按照 类名::静态成员变量名 的方式访问的
public:
typedef typename Iterator::Ref Ref;
typedef typename Iterator::Ptr Ptr;
typedef ReverseListIterator<Iterator> Self;
public:
//
// 构造
ReverseListIterator(Iterator it): _it(it){}
//
// 具有指针类似行为
Ref operator*(){
Iterator temp(_it);
--temp;
return *temp;
}
Ptr operator->(){ return &(operator*());}
//
// 迭代器支持移动
Self& operator++(){
--_it;
return *this;
}
Self operator++(int){
Self temp(*this);
--_it;
return temp;
}
Self& operator--(){
++_it;
return *this;
}
Self operator--(int)
{
Self temp(*this);
++_it;
return temp;
}
// 迭代器支持比较
bool operator!=(const Self& l)const{ return _it != l._it;}
bool operator==(const Self& l)const{ return _it != l._it;}
Iterator _it;
};
7.listvector的对比
vector list 都是 STL 中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及
应用场景不同,不同如下。

 

vector
list
动态顺序表,一段连续空间
带头结点的双向循环链表
访
支持随机访问,访问某个元素效率 O(1)
不支持随机访问,访问某个元 素效率 O(N)
入和
任意位置插入和删除效率低,需要搬移元素,时间 复杂度为 O(N) ,插入时有可能需要增容,增容: 开辟新空间,拷贝元素,释放旧空间,导致效率更
任意位置插入和删除效率高, 不需要搬移元素,时间复杂度 O(1)
底层为连续空间,不容易造成内存碎片,空间利用 率高,缓存利用率高
底层节点动态开辟,小节点容 易造成内存碎片,空间利用率 低,缓存利用率低
原生态指针
对原生态指针 ( 节点指针 ) 进行
封装
在插入元素时,要给所有的迭代器重新赋值,因为 插入元素有可能会导致重新扩容,致使原来迭代器 失效,删除时,当前迭代器需要重新赋值否则会失
插入元素不会导致迭代器失 效,删除元素时,只会导致当 前迭代器失效,其他迭代器不 受影响
使
需要高效存储,支持随机访问,不关心插入删除效
大量插入和删除操作,不关心 随机访问

 


 

 

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

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

相关文章

C++ 进阶:类相关特性的深入探讨

⭐在对C 中类的6个默认成员函数有了初步了解之后&#xff0c;现在我们进行对类相关特性的深入探讨&#xff01; &#x1f525;&#x1f525;&#x1f525;【C】类的默认成员函数&#xff1a;深入剖析与应用&#xff08;上&#xff09; 【C】类的默认成员函数&#xff1a;深入剖…

python实战项目46:selenium爬取百度新闻

python实战项目46:selenium爬取百度新闻 一、项目简介二、完整代码一、项目简介 思路是首先使用selenium打开百度新闻页面,然后实现翻页操作,获取每条新闻的标题和链接。接下来的问题是,在遍历标题和链接,对每一个链接发送请求时,发现会弹出百度安全验证,本文的思路是使…

浪潮云启操作系统(InLinux)bcache缓存实践:理解OpenStack环境下虚拟机卷、Ceph OSD、bcache设备之间的映射关系

前言 在OpenStack平台上&#xff0c;采用bcache加速ceph分布式存储的方案被广泛用于企业和云环境。一方面&#xff0c;Ceph作为分布式存储系统&#xff0c;与虚拟机存储卷紧密结合&#xff0c;可以提供高可用和高性能的存储服务。另一方面&#xff0c;bcache作为混合存储方案&…

新版idea菜单栏展开与合并

新版idea把菜单栏合并了看着很是不习惯&#xff0c;找了半天原来在这里展开 ① 点击文件 -> 设置 ② 点击外观与行为 -> 外观 -> 合并主菜单和窗口标题 然后确定&#xff0c;重启即可

HTML作业

作业 复现下面的图片 复现结果 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><form action"#"method"get"enctype"text/plain"><…

演示:基于WPF的DrawingVisual开发的高刷新率示波器

一、目的&#xff1a;分享一个基于WPF的DrawingVisual开发的高刷新率示波器 二、效果演示 特此说明&#xff1a;由于Gif录制工具帧率不够&#xff0c;渲染60帧用了4.6秒&#xff0c;平均帧率在12Hz左右&#xff0c;所以展示效果不好&#xff0c;想要看好些的效果可以看文章下面…

【目标检测2024】DetCLIP

算法介绍 CLIP&#xff08;Contrastive Language-Image Pre-Training&#xff09;模型是一种多模态预训练神经网络&#xff0c;由OpenAI在2021年发布&#xff0c;是从自然语言监督中学习的一种有效且可扩展的方法。CLIP在预训练期间学习执行广泛的任务&#xff0c;包括OCR&…

DORA 机器人中间件学习教程(6)——激光点云预处理

文章目录 1 移植思路2 代码输入输出说明3 编写CmakeList.txt文件4 编写yml文件5 编译并启动节点参考资料 在DORA中通过驱动获取激光雷达数据后&#xff0c;激光点云预处理部分代码是参考了autoware官方代码并对其进行裁剪得到的&#xff0c;点云预处理主要包含三个节点&#xf…

32.第二阶段x86游戏实战2-遍历技能2(技能二叉树基址)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

[数据集][目标检测]电力场景输电线路巡检检测数据集VOC+YOLO格式8667张50类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8667 标注数量(xml文件个数)&#xff1a;8667 标注数量(txt文件个数)&#xff1a;8667 标注…

双碳目标下储能产业新趋势与架构

0.引言 储能技术涉及能量的存储和利用&#xff0c;对电力系统平衡至关重要。它允许电力在需求时被储存和释放&#xff0c;对电力生产和消费方式产生重大影响。随着全球应对气候变化&#xff0c;风能和太阳能成为主要能源&#xff0c;但其不稳定性需要储能技术来提高可靠性。储…

在做题中学习(65):Z字形变换

6. Z 字形变换 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;模拟 思路&#xff1a;把原字符串从上到下依次读取到新字符串中&#xff0c;就需要看看Z字形变换时字符变化的规律。 以行数h4时为例&#xff1a; 对于第一行和最后一行&#xff1a; 每一个字符的下标…

Java笔试06

在Java中&#xff0c;异常可以分为两大类&#xff1a;编译时异常&#xff08;编译时检查异常&#xff09;和运行时异常&#xff08;非编译时检查异常&#xff09;。 编译时异常&#xff08;Checked Exceptions&#xff09;是指在编译时期必须被捕获或声明抛出的异常。这些异常…

基于springboot家乡特色推荐系统

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 系统展示 【2024最新】基于JavaSpringBootVueMySQL的&#xff0c;前后端分离。 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;…

Q宠大乐斗批量好友添加器(基于python实现)

效果如下: 只要有自动化测试的浏览器和插件就能批量添加等级相近的陌生人为好友,过程迅速,分两个py文件 第一个是主程序: import tkinter as tk import re from tkinter import scrolledtext, font, ttk, messagebox, filedialog from selenium import webdriver from se…

10_实现readonly

在某些时候&#xff0c;我们希望定义一些数据是只读的&#xff0c;不允许被修改&#xff0c;从而实现对数据的保护&#xff0c;即为 readonly 只读本质上也是对数据对象的代理&#xff0c;我们同样可以基于之前实现的 createReactiveObject 函数来实现&#xff0c;可以为此函数…

Unable to open nested entry ‘********.jar‘ 问题解决

今天把现网版本的task的jar拖回来然后用7-zip打开拖了一个jar进去替换mysql-connector-java-5.1.47.jar 为 mysql-connector-java-5.1.27.jar 启动微服务的时候就报错下面的 Exception in thread "main" java.lang.IllegalStateException: Failed to get nested ar…

OS管理和进程的学习

1.冯诺依曼体系结构 1.1 输入设备&#xff1a;键盘&#xff0c;鼠标&#xff0c;键盘&#xff0c;网卡&#xff08;网络接受&#xff09;&#xff0c;磁盘... 输出设备&#xff1a;显示器&#xff0c;磁盘&#xff0c;网卡&#xff08;网络发送&#xff09; .... 存储器&…

CTFHUB技能树之SQL——字符型注入

开启靶场&#xff0c;打开链接&#xff1a; 直接指明是SQL字符型注入&#xff0c;但还是来判断一下 &#xff08;1&#xff09;检查是否存在注入点 1 and 11# 返回正确 1 and 12# 返回错误 说明存在SQL字符型注入 &#xff08;2&#xff09;猜字段数 1 order by 2# 1 order…

Shell重定向输入输出

我的后端学习大纲 我的Linux学习大纲 重定向介绍 标准输入介绍 从键盘读取用户输入的数据&#xff0c;然后再把数据拿到Shell程序中使用&#xff1b; 标准输出介绍 Shell程序产生的数据&#xff0c;这些数据一般都是呈现到显示器上供用户浏览查看; 默认输入输出文件 每个…