STL-list

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来说这可能是一个重要的因素)

2.list的使用

2.1 构造函数

void test1()
{//无参构造list<int> l1;//有参构造list<int> l2(10, 1);//10个1list<int> l3(10);//使用迭代器范围构造list<int> l4(l2.begin(), l2.end());//双向迭代器不支持加减法vector<int> v = { 1,2,3,4,5 };list<int> l5(v.begin() + 2, v.end());//拷贝构造list<int> l6(l5);//使用initializer_list初始化list<int> l7 = { 1,2,3,4,5,6,7,8 };
}

2.2operator=()

 赋值运算符重载,进行深拷贝

//int类型
void PrintList(const list<int>& l)
{for (auto e : l){cout << e << ' ';}cout << endl;
}void test2()
{//operator=list<int> l1 = { 1,2,3 };list<int> l2;//深拷贝l2 = l1;PrintList(l1);PrintList(l2);
}

 2.3begin() 和 end()

begin():返回第一个元素的双向迭代器,如果容器为空,则返回的迭代器值不能被解引用。
end():返回最后一个元素的下一位双向迭代器,如果容器为空,返回的迭代器与begin()返回的迭代器相同。
双向迭代器不支持加减法,支持 ++ 、 -- 、 * 、 == 、 != 、= 等操作。

void test3()
{//begin() and end()list<int> l = { 1,2,3,4,5,6,7,8 };list<int>::iterator it = l.begin();//返回双向迭代器while (it != l.end()){cout << *(it++) << ' ';}cout << endl;
}

2.4 rbegin() 和 rend()

rbegin():返回最后一个元素的反向双向迭代器
rend():返回第一个元素前一位的反向双向迭代器
使用++是向前迭代,--是向后迭代

void test4()
{list<int>l = { 1,2,3,4,5,6,7,8 };list<int>::reverse_iterator it = l.rbegin();while (it != l.rend()){cout << *(it++) << ' ';}cout << endl;
}

2.5 cbegin()、cend()、crbegin()、 crend()

无论调用对象是否const修饰,这四个函数返回const迭代器,不能通过迭代器修改指向内容,但迭代器本身可以改变。

2.6 empty()

判断容器是否为空,空返回true,非空返回false

void test5()
{list<int>l = { 1,2,3,4,5,6,7,8 };while (!l.empty()){cout << l.front() << ' ';l.pop_front();}
}

2.7 size()

用于返回有效元素个数

 

2.8 front()

返回容器第一个元素的引用,对空容器使用front是未定义行为

 


2.9 back()

返回容器最后一位元素的引用,对空容器使用back是未定义行为

2.10 assign()

将新内容替换原本的全部内容

void test8()
{//assignlist<int> l1 = { 1,2,3,4,5 };list<int> l2 = { 11,22 };vector<int> v = { 121,23,43,54,54,5,454 };//范围替换l1.assign(v.begin(), v.begin() + 3);l2.assign(l1.begin(), l1.end());PrintList(l1);PrintList(l2);//n个val替换l1.assign(10, 2);l2.assign(2, 0);PrintList(l1);PrintList(l2);
}

2.11 emplace_front

在开头构造并插入元素
在列表的开头插入一个新元素,就在它当前的第一个元素之前。这个新元素是使用args作为其构造的参数来就地构造的
​这有效地将容器大小增加了1。
​该元素是通过调用allocator_traits::construct来就地构造的,并将参数转发。
​存在一个类似的成员函数push_front,它复制或移动一个现有对象到容器中。

class A
{
public:A(int a, int b):_a(a), _b(b){cout << "构造" << endl;}A(const A& a){cout << "拷贝构造" << endl;}void Print(){cout << _a << ' ' << _b << endl;}
private:int _a;int _b;
};
void test10()
{list<A> l1;list<A> l2;l1.emplace_front(1,2);//直接构造并成为l1的元素//l2.push_front(1, 2);//errorl2.push_front({ 2,3 });//先隐式类型转换构造,再拷贝构造成l2的元素(*l1.begin()).Print();(*l2.begin()).Print();
}

 2.12 push_front()

在容器第一个元素前插入一个元素, val的内容被拷贝(或移动)到插入的元素。
push_back()执行拷贝行为还是移动行为取决于传递给它的参数类型,传递左值触发拷贝构造函数执行拷贝行为,传递右值触发移动构造函数执行移动操作
(在 C++ 中,左值(lvalue)和 右值(rvalue)是用来区分表达式的值在内存中的存在方式和生命周期的术语。)

移动构造函数是 C++11 引入的一种特殊构造函数,旨在高效地转移资源的所有权,而不是进行昂贵的复制。它通过移动语义来减少不必要的拷贝,提高程序性能。

移动构造函数通常在以下情况下被调用:

  1. 对象临时生命周期结束后:当你通过一个临时对象(右值)初始化另一个对象时,移动构造函数会被调用。
  2. 使用 std::move:当你显式调用 std::move 函数将一个对象转换为右值引用时,会触发移动构造函数。

 2.13 pop_front()

用于删除第一个元素 
 

2.14 emplace_back()

在末尾构造并插入元素

2.15 push_back()


在最后一个元素之后插入一个元素,val的内容被拷贝(或移动)到新元素。

2.16 pop_back()


删除最后一个元素

2.17 emplace()


在pos位置的元素之前构造并插入一个元素

2.18 insert()

 在指定位置的元素之前插入新元素(一个或多个)

void test13()
{list<int> l1 = {1,2,3};vector<int> v = { 444,555,666,777 };auto it = l1.begin();//iterator insert (const_iterator position, const value_type& val);l1.insert(it, 0);PrintList(l1);//iterator insert (const_iterator position, size_type n, const value_type& val);it++;l1.insert(it, 3, 6);PrintList(l1);//template <class InputIterator>//iterator insert(const_iterator position, InputIterator first, InputIterator last);l1.insert(l1.begin(), v.begin() + 2, v.end());PrintList(l1);//iterator insert (const_iterator position, value_type&& val);//右值引用l1.insert(it, 9);PrintList(l1);//iterator insert(const_iterator position, initializer_list<value_type> il);l1.insert(it, { 11,12,13,14,15 });PrintList(l1);
}

 2.19 erase()

从容器中删除一个或者范围内的元素

 2.20 swap()


交换两个容器的内容


2.21 resize()

调整容器的有效元素的个数,使其包含n个元素
n小于当前个数,元素将减少到前n个,超出部分删除并销毁
n大于当前个数,元素将尾插至n个,如果指定了val,则新元素初始化为val的副本 

class A
{
public:A(){cout << "无参构造" << endl;}A(int a, int b):_a(a), _b(b){cout << "有参构造" << endl;}A(const A& a){cout << "拷贝构造" << endl;}void Print(){cout << _a << ' ' << _b << endl;}
private:int _a;int _b;
};void test14()
{list<A> l1;l1.resize(2, {1,1});cout << "------" << endl;l1.resize(5);//3个无参构造
}

2.22 clear()

删除容器的所有内容

2.23 splice()

用于将元素从一个list转移到另一个list(转移:将元素从原来的list移除,原封不动转移到另一个list) 

2.24  remove()

 从容器中删除所有与val相同的元素

2.25 remove_if()


用于从容器中移除满足特定条件的元素
remove_if()传入一个谓语函数(返回bool值的函数)

2.26 unique()


删除相邻val值重复的元素
需要给整个容器去重:先排序,再unique

2.27  merge()


用于将两个已排序的列表合并成一个排序后的列表。需要注意的是,两个列表必须都是按顺序排列的。合并操作会通过移动节点来达成,而不需要额外分配内存。
两个列表的排序方式需要与合并成一个列表后的排序方式保持一致(即两个升序列表合并成一个升序列表,两个降序列表合并成一个降序列表)

 

2.28 sort()

sort() 函数会对列表中的元素进行升序排序。默认情况下,它使用元素的 < 运算符进行比较, 也可以提供一个自定义的比较函数。 
list的sort()底层是基于归并排序实现的,归并排序在处理链表时的性能非常优越,因为它可以高效地操作节点而不需要额外的空间消耗。归并排序通过分割链表和合并已排序的部分,能够快速地处理链表的节点。

 2.29 reverse()

 用于反转list

2.30 关系运算符重载(非成员函数)

 3.operator->()

为了可读性,强制剩下一个->  
 

4. 部分模拟实现

#pragma once
#include<assert.h>namespace myList
{template<class T>struct ListNode{ListNode<T>* _next;ListNode<T>* _prev;T _data;ListNode(const T& data = T()):_next(nullptr),_prev(nullptr),_data(data){}};template<class T, class Ref, class Ptr>struct ListIterator{typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;Node* _node;ListIterator(Node* node):_node(node){}// ++it;Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const Self& it){return _node != it._node;}bool operator==(const Self& it){return _node == it._node;}};//template<class T>//class ListConstIterator//{//	typedef ListNode<T> Node;//	typedef ListConstIterator<T> Self;//	Node* _node;//public://	ListConstIterator(Node* node)//		:_node(node)//	{}//	// ++it;//	Self& operator++()//	{//		_node = _node->_next;//		return *this;//	}//	Self& operator--()//	{//		_node = _node->_prev;//		return *this;//	}//	Self operator++(int)//	{//		Self tmp(*this);//		_node = _node->_next;//		return tmp;//	}//	Self& operator--(int)//	{//		Self tmp(*this);//		_node = _node->_prev;//		return tmp;//	}//	//*it//	const T& operator*()//	{//		return _node->_data;//	}//	const T* operator->()//	{//		return &_node->_data;//	}//	bool operator!=(const Self& it)//	{//		return _node != it._node;//	}//	bool operator==(const Self& it)//	{//		return _node == it._node;//	}//};template<class T>class list{typedef ListNode<T> Node;public:// 不符合迭代器的行为,无法遍历//typedef Node* iterator;//typedef ListIterator<T> iterator;//typedef ListConstIterator<T> const_iterator;typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;iterator begin(){//iterator it(_head->_next);//return it;return iterator(_head->_next);}const_iterator begin() const{return const_iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator end() const{return const_iterator(_head);}void empty_init(){_head = new Node();_head->_next = _head;_head->_prev = _head;}list(){empty_init();}list(initializer_list<T> il){empty_init();for (const auto& e : il){push_back(e);}}// lt2(lt1)list(const list<T>& lt){empty_init();for (const auto& e : lt){push_back(e);}}// lt1 = lt3list<T>& operator=(list<T> lt){swap(_head, lt._head);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}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;*/insert(end(), x);}void pop_back(){erase(--end());}void push_front(const T& x){insert(begin(), x);}void pop_front(){erase(begin());}// 没有iterator失效iterator insert(iterator pos, const T& x){Node* cur = pos._node;Node* newnode = new Node(x);Node* prev = cur->_prev;// prev  newnode  curprev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;return iterator(newnode);}// erase 后 pos失效了,pos指向节点被释放了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 iterator(next);}private:Node* _head;};
}

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

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

相关文章

黑马Java零基础视频教程精华部分_12_面向对象进阶(4)_内部类

《黑马Java零基础视频教程精华部分》系列文章目录 黑马Java零基础视频教程精华部分_1_JDK、JRE、字面量、JAVA运算符 黑马Java零基础视频教程精华部分_2_顺序结构、分支结构、循环结构 黑马Java零基础视频教程精华部分_3_无限循环、跳转控制语句、数组、方法 黑马Java零基础视…

IEEE Trans系列,超低自引率,沾边可收,截稿在即,版面有限!

关注GZH【欧亚科睿学术】&#xff0c;第一时间了解期刊最新动态&#xff01; &#x1f447; &#x1f447; &#x1f447; &#x1f447; 这本IEEE Trans系列&#xff01;指标优秀&#xff01; IEEE-Trans系列期刊IEEE TRANSACTIONS ON INTELLIGENT VEHICLES (查看原文)…

详解直铺防静电瓷砖的特点与优势

防静电地板分为架空防静电地板和直铺防静电地板&#xff0c;直铺式防静电地板是一种直接铺设在地面上的地板系统&#xff0c;防静电瓷砖就是常用的直铺防静电地板之一。防静电瓷砖是在瓷砖烧制过程中加入防静电功能粉体进行物理改性&#xff0c;规格为600*600*10mm&#xff0c;…

前端常用的几个工具网站

觉得不错的前端工具类网站 1、Grid布局生成 https://cssgrid-generator.netlify.app 2、拟物按钮样式生成 https://neumorphism.io 3、玻璃形态效果 在线制作CSS玻璃形态 4、一些Button、checkBox、switch、card的css样式 零代码 - 精美CSS样式库 5、CSS阴影生成 在线创建…

学习c语言第二十天(自定义类型)

一、结构体 1.结构体声明 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.1结构体的声明 struct stu {char name[20];int age; }s1,s2;//s1,s2是struct stu 类型的变量&#xff0c;//可以不创建&#xff0c;在main函数里创建 …

进程的管理与控制详解:创建、终止、阻塞等待与非阻塞等待

目录 一、进程创建 1、实例 2、fork函数详解 (1)fork函数模板 (2). fork() 函数的工作原理 (3). fork() 返回值和错误处理 3、如何理解进程创建过程 二、进程终止 1、终止是在做什么&#xff1f; 2、进程终止&#xff0c;有三种情况 3、进程如何终止&#xff1f; 三…

【独家原创RIME-CNN-LSSVM】基于霜冰优化算法优化卷积神经网络(CNN)结合最小二乘向量机(LSSVM)的数据回归预测

【独家原创RIME-CNN-LSSVM】基于霜冰优化算法优化卷积神经网络(CNN)结合最小二乘向量机(LSSVM)的数据回归预测 目录 【独家原创RIME-CNN-LSSVM】基于霜冰优化算法优化卷积神经网络(CNN)结合最小二乘向量机(LSSVM)的数据回归预测效果一览基本介绍程序设计参考资料 效果一览 基本…

c->c++(四):gtest

本文主要探讨gtest相关内容。 gtest安装 wget -O gtest.zip https://github.com/google/googletest/archive/refs/heads/main.zipunzip gtest.zipcd googletest-mainmkdir bulid && cd buildcmake .. && make && make install gtest API TEST/TEST…

Redis02——缓存(缓存更新策略、缓存穿透、缓存雪崩、缓存击穿、缓存工具封装)

目录 缓存概念 添加Redis缓存 业务场景 缓存作用模型 java代码 缓存更新策略 主动更新的三种策略 主动更新——Cache Aside Pattern 实际应用 缓存穿透 概念 解决方法 实际应用 缓存雪崩 概念 解决方法 缓存击穿 互斥锁 介绍 实际应用 逻辑过期 介绍 实际…

基于Yolov8面部七种表情检测与识别C++模型部署

表情识别 七种表情识别是一个多学科交叉的研究领域&#xff0c;它结合了心理学、认知科学、计算机视觉和机器学习等学科的知识和技术。 基本概念 表情的定义&#xff1a;表情是人们在情绪体验时面部肌肉活动的结果&#xff0c;是人类情感交流的基本方式之一。基本表情理论&a…

使用Step Functions运行AWS Backup时必备的权限要点

引言 在尝试从Step Functions执行AWS Backup的按需备份时&#xff0c;我在权限方面遇到了一些困难。为了备忘&#xff0c;我将这些经验写成这篇文章。 概述 从Step Functions执行AWS Backup时&#xff0c;需要分配以下权限&#xff1a; AWS Backup相关权限 执行备份的权限…

Java: 线程安全问题的解决方案(synchronized)

发生原因 要想解决线程安全问题,那么我们首先得知道线程安全问题为什么会发生. 发生原因: 线程在操作系统中是"随机调度,抢占式执行的"[根本原因].多个线程,同时修改同一个变量修改操作不是"原子"的内存可见性问题指令重排序 解决方案 原因1和2,我们很…

04:【stm32】LED编程和按键控制

LED编程和按键控制 1、LED编程1.1、点亮一课LED灯 2、按键控制2.1、通过一个按钮控制LED灯的亮灭 1、LED编程 1.1、点亮一课LED灯 首先&#xff0c;我们想象一下&#xff0c;让LED灯点亮&#xff0c;引脚应该是输出模式&#xff0c;那么应该是通用模式&#xff0c;还是复用模式…

打靶记录7——Hacker_Kid-v1.0.1

靶机下载地址 https://download.vulnhub.com/hackerkid/Hacker_Kid-v1.0.1.ova难度 OSCP 风格的中级难度靶机&#xff08;只需要获取root权限即可&#xff0c;CTF 风格的靶机就还需要获取flag&#xff09; 涉及的攻击方法&#xff1a; 主机发现端口扫描Web信息收集DNS区域传…

Redis2-Redis常见命令

目录 Redis数据结构介绍 Redis通用命令 KEYS DEL EXISTS EXPIRE String类型 Key的层级格式 Hash类型 List类型 Set类型 SortedSet类型 Redis数据结构介绍 Redis是一个key-value的数据库&#xff0c;key一般是String数据库&#xff0c;value的类型多种多样 可以通过…

《Unity3D网络游戏实战》学习与实践--制作一款大乱斗游戏

角色类 基类Base Human是基础的角色类&#xff0c;它处理“操控角色”和“同步角色”的一些共有功能&#xff1b;CtrlHuman类代表“操控角色”​&#xff0c;它在BaseHuman类的基础上处理鼠标操控功能&#xff1b;SyncHuman类是“同步角色”类&#xff0c;它也继承自BaseHuman&…

解决电脑缺少.NET组件?手把手教你轻松解决

在日常使用电脑的过程中&#xff0c;很多用户可能会遇到“电脑缺少.NET组件”的提示&#xff0c;这可能导致某些应用程序无法正常运行或安装。那么&#xff0c;.NET组件到底是什么&#xff1f;为何它如此重要&#xff1f;本文将为您详细解答这些问题&#xff0c;并提供有效的解…

[ACM MM 2024] Wave-Mamba:超高清暗光图像增强的小波状态空间模型

Wave-Mamba: Wavelet State Space Model for Ultra-High-Definition Low-Light Image Enhancement (arxiv.org) Wave-Mamba是一种用于增强超高清低光照图像的新模型&#xff0c;它引入了低频状态空间块和高频增强块&#xff0c;并取得了领先水平的性能。该模型即将开源&#x…

用Python插入表格到PowerPoint演示文稿

有效的信息传达是演示文稿中的重点&#xff0c;而PowerPoint演示文稿作为最广泛使用的演示工具之一&#xff0c;提供了丰富的功能来帮助演讲者实现这一目标。其中&#xff0c;在演示文稿中插入表格可以帮助观众更直观地理解数据和比较信息。通过使用Python这样的强大编程语言&a…

【STL】 vector的底层实现

1.vector的模拟代码完整实现&#xff08;后面会拆分开一个一个细讲&#xff09; #pragma once #include<assert.h>// 抓重点namespace bit {/*template<class T>class vector{public:typedef T* iterator;private:T* _a;size_t _size;size_t _capacity;};*/templa…