STL容器--list

1. list的介绍及使用
1.1 list的介绍

1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指其前一个元素和后一个元素。

3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。

4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。

5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

1.2 list的使用

list中的接口比较多,此处类似,只需要掌握如何正确的使用,然后再去深入研究背后的原理,已达到可扩展的能力。以下为list中一些常见的重要接口:

1.2.1 list的构造
 

1.2.2 list iterator的使用

list迭代器可以理解成一个指针,该指针指向list中的某个节点。实际它是指针的封装。

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


1.2.3 list capacity

1.2.4 list element access

int main()
{//list<int> lt(3);vector<int> v{ 4,5 };vector<string> tokens{ "4","13","5","/","+" };cout<<evalRPN(tokens)<<endl;list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);//这里可以直接修改里面第一个元素的值lt.front() = 10;  for (auto e : lt){cout << e << " ";}cout << endl;return 0;
}

1.2.5 list modifiers

以下代码对部分接口进行测试:

	void testlist3(){list<int> lt;lt.push_front(1);lt.push_front(2);lt.push_front(3);lt.push_front(4);lt.push_front(5);for (auto e : lt){cout << e << " ";}cout << endl;list<int> lt1;lt1.push_front(10);lt1.push_front(20);lt1.push_front(30);lt1.push_front(40);lt.swap(lt1);for (auto e : lt){cout << e << " ";}cout << endl<<"头删后:"<<endl;lt.erase(lt.begin());for (auto e : lt){cout << e << " ";}cout << endl;}

1.2.6 list的迭代器失效

迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

删除list容器的所有值 正确写法:

void TestListIterator()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array + sizeof(array) / sizeof(array[0]));for (auto e : l){cout << e <<" ";}auto it = l.begin();while (it != l.end()){//此时it已经指向原来it的下一个迭代器位置l.erase(it++); // it = l.erase(it);//下面两行为错误写法//l.erase(it);//++it;}for (auto e : l){cout << e <<endl;}
}

2. list的模拟实现

2.1 模拟实现list

要模拟实现list,必须要熟悉list的底层结构以及其接口的含义,通过上面的学习,这些内容已基本掌握,现在我们来模拟实现list。

namespace xwy {template<typename T>struct listNode{T _data;listNode<T>* _pre;listNode<T>* _next;//单参数构造函数listNode(const T& val = T()):_data(val),_pre(nullptr),_next(nullptr){}};template<typename T, class Ref, class Ptr>struct _list_iterator{//  受类域的限制typedef listNode<T> Node;typedef _list_iterator<T,Ref,Ptr> self;Node* _node;_list_iterator(Node *node=nullptr):_node(node){}//操作符重载Ref operator*(){return _node->_data;}Ptr operator->(){return &(_node->_data);}self& operator--(){_node = _node->_pre;return *this;}self operator-(int a){Node* ptr = _node;while (a--&&ptr){ptr = ptr->_pre;}return ptr;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){//  self tmp(*this)  拷贝构造自己Node* tmp = _node;_node = _node->_next;return tmp;}bool operator!=(const self& node)const{return _node != node._node;}};// 适配器 -- 复用template<class Iterator, class Ref, class Ptr>struct Reverse_iterator{Iterator _it;typedef  Reverse_iterator<Iterator, Ref, Ptr> self;Reverse_iterator(const Iterator &it):_it(it){}//操作符重载Ref operator*(){return *_it;}self& operator--(){++_it;return *this;}Ptr operator->(){return &(*_it);}self& operator++(){--_it;return *this;}self operator++(int){//  self tmp(*this)  拷贝构造自己Iterator it = _it;--_it;return it;}bool operator!=(const self& lt) const   //const和const比较 ,非const和const比较{return lt._it != _it;   //不支持那两种类型的比较,是因为不存在那两种类型比较的重载}};template<typename T>class list{public:typedef listNode<T> Node;typedef _list_iterator<T,T&,T*> iterator;   typedef _list_iterator<T, const T&, const T*> const_iterator;typedef Reverse_iterator<iterator,T&,T*> reverse_iterator;typedef Reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;//无参构造函数list(){empty_init();}template<class iterator>list(iterator first,iterator last){empty_init();while (first != last){push_back(*first);first++;}}//拷贝构造list(const list& lt){empty_init();auto it = lt.begin();while (it != lt.end()){push_back(*it);it++;}}//迭代器的实现iterator begin() {return _head->_next;}iterator end() {return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}//反向迭代器reverse_iterator rbegin(){return --end();}reverse_iterator rend(){return --begin();}const_reverse_iterator rbegin() const{return --end();}const_reverse_iterator rend() const{return --begin();}void push_back(const T& val){Node* newnode = new Node(val);newnode->_next = _head;_head->_pre->_next = newnode;newnode->_pre = _head->_pre;_head->_pre = newnode;}iterator erase(iterator pos) //在pos位置删除{Node* cur = pos._node;Node* prev = cur->_pre;Node* next = cur->_next;delete cur;prev->_next = next;next->_pre = prev;return next;}// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* cur = pos._node;Node* newNode = new Node(val);newNode->_next = cur;newNode->_pre = cur->_pre;cur->_pre->_next = newNode;cur->_pre = newNode;return pos;}/*void push_back(const T& val){insert(_head, val);}*/void push_front(const T& val){insert(_head->_next, val);}void swap(list<T>& l){std::swap(l._head, _head);}void clear(){//清理数据,不清头节点iterator it = begin();while (it != end()){it = erase(it);//it就是下一个位置}}~list(){clear();delete _head;		// 只有节点是new出来,需要delete,但这个只delete 了一个节点}private:void empty_init(){_head = new Node();_head->_next = _head->_pre = _head;}Node* _head;  };

2.2 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;
};

3. list与vector的对比

vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不同,其主要不同如下:

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

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

相关文章

面试官:对于MQ中的消息丢失你是如何理解的?

相信很多的小伙伴在面试的时候&#xff0c;涉及到MQ的面试题&#xff0c;消息丢失是必问面试题之一。那么对于消息丢失你又是如何理解的呢&#xff1f; 下面我们一起来看一下。 本文以 Kafka 举例说明 一、什么是消息丢失&#xff1f; 消息丢失的定义是&#xff1a;在消息传递…

【动手学深度学习】softmax回归从零开始实现的研究详情

目录 &#x1f30a;1. 研究目的 &#x1f30a;2. 研究准备 &#x1f30a;3. 研究内容 &#x1f30d;3.1 softmax回归的从零开始实现 &#x1f30d;3.2 基础练习 &#x1f30a;4. 研究体会 &#x1f30a;1. 研究目的 理解softmax回归的原理和基本实现方式&#xff1b;学习…

Python打印当前目录下,所有文件名的首字母

代码如下&#xff1a; #!/usr/bin/env python3 """ 按顺序打印当前目录下&#xff0c;所有文件名的首字母&#xff08;忽略大小写&#xff09; """ import sys from pathlib import Pathdef main() -> None:ps Path(__file__).parent.glob(…

代码随想录算法训练营第26天(py)| 回溯 | 39. 组合总和、40.组合总和II、131.分割回文串

39. 组合总和 力扣链接 给定一个无重复元素的数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的数字可以无限制重复被选取。 说明&#xff1a; 所有数字&#xff08;包括 target&#xff09;都是正整数…

上传RKP 证书签名请求息上传到 Google 的后端服务器

上传证书签名请求 1.准备环境&#xff1a;OK pip3 install google-auth2.13.0 requests2.28下载 device_info_uploader.py 。 没找到先跳过 选项 1&#xff1a;通过 GCP 帐户使用 device_info_uploader.py 运行脚本。 ./device_info_uploader.py --credentials /secure/s…

NFS服务p.2 用户的上传与下载,以及用户映射

如何进行上传和下载呢&#xff1f; 目录 如何进行上传和下载呢&#xff1f; 上传 访问时的账户映射对于上传文件和下载文件的影响&#xff1f; 在服务器里进行修改用户的权限 如和修改使用用户上传时的名字&#xff1f; 上传 上传的话&#xff0c;因为我们现在所在的nfs1…

端午佳节到,礼轻情意重,闪侠惠递帮你高效便宜寄快递

马上就是端午佳节了&#xff0c;我们通常会吃粽子&#xff0c;赛龙舟&#xff0c;但是这些礼物我们该怎么快速的送到我们亲朋好友的手中呢&#xff1f;小编这里非常推荐大家使用闪侠惠递来寄快递。不仅能高效便捷的把礼物送到你的手中&#xff0c;而且还能以非常便宜的价格呢&a…

03_初识Spring Cloud Gateway

文章目录 一、网关简介1.1 网关提出的背景1.2 网关在微服务中的位置1.3 网关的技术选型1.4 补充 二、Spring Cloud Gateway的简介2.1 核心概念&#xff1a;路由&#xff08;Route&#xff09;2.2 核心概念&#xff1a;断言&#xff08;Predicate&#xff09;2.3 核心概念&#…

linux系统——性能检测工具glances

在linux系统中&#xff0c;由python开发的glances工具是一个功能强大的性能检测工具 可以通过yum进行安装 安装glances后&#xff0c;进入命令界面 glance支持网站模式&#xff0c;将监控到的数据以网站形式显示出来 这里需要用python包管理命令 使用glances -w开放…

linux中最基础使用的命令

小白学习记录&#xff1a; 前情提要&#xff1a;Linux命令基础格式!查看 ls看目录的小技巧 进入指定目录 cd查看当前工作目录 pwd创建一个新的目录(文件夹&#xff09; mkdir创建文件 touch查看文件内容 cat、more操作文件、文件夹- 复制 cp- 移动 mv- 删除【危险操作&#xff…

PostgreSQL 远程登录postgres用户不需要密码?免密登录权限设置

PostgreSQL 安装之后&#xff0c;发现登录postgres用户时不需要密码。原因配置远程IP时&#xff0c;IP 地址对应的 method 设置成了 trust。 今天安全测试反馈&#xff0c;pgsql有弱口令问题&#xff0c;于是上去改了pgsql的密码&#xff0c;结果问题还没解决。查看了具体的问…

docker运行centos提示Operation not permitted

1、在docker中运行了centos7镜像 2、进入到centos容器中使用systemctl命令时提示 systemctl Failed to get D-Bus connection: Operation not permitted 3、解决办法 在运行centos镜像的时候加上--privileged参数 4、附上docker官网命令说明截图

OpenHarmony父子组件单项同步使用:@Prop装饰器

Prop装饰的变量可以和父组件建立单向的同步关系。Prop装饰的变量是可变的&#xff0c;但是变化不会同步回其父组件。 说明&#xff1a; 从API version 9开始&#xff0c;该装饰器支持在ArkTS卡片中使用。 概述 Prop装饰的变量和父组件建立单向的同步关系&#xff1a; ● P…

C语言(数据存储)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#xff0c;在这里撰写成文一…

贪心,CF802B. Heidi and Library

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 802A - Codeforces 二、解题报告 1、思路分析 这个题相当于你有一个容量为K的Cache&#xff0c;然后给你一系列访存序列 当访问缺失时你不得不替换掉Cache中某些块 学过操作系统都很熟悉页面置…

anaconda怎么运行python

一、在Anaconda Navigator中运行 首先点击菜单栏中的“开始”&#xff0c;在搜索栏中输入“Anaconda”&#xff0c;然后选择“Anaconda Navigator”。 进入主界面&#xff0c;点击“Spyder”中的“Launch”即可。 然后按F5键运行即可。 二、在Anaconda Prompt中运行 也可以在…

Linux - 高级IO

目录 理解五种IO模型非阻塞IO的设置多路转接之select 实现一个简易的select服务器select服务器的优缺点 多路转接之poll 实现一个简易的poll服务器poll服务器的优缺点 多路转接之epoll epoll原理epoll的优势用epoll实现一个简易的echo服务器 epoll的LT和ET工作模式 什么是LT和…

PasteSpider之阿里云OSS功能的设计初衷

前言 在版本v24.6.2.1之后&#xff0c;有一个菜单"OSS配置"&#xff0c;这个配置是干嘛用的呢&#xff1f; 阿里云OSS&#xff0c;或者说云盘&#xff0c;我觉得也可以当CDN使用&#xff0c;比如我们部署了一个网站&#xff0c;为了减少服务器的承载&#xff0c;可以…

数据结构汇总

等同于&#xff1a; 旋转的时候忽略Nil,选装完再加上。