c++编程14——STL(3)list

欢迎来到博主的专栏:c++编程
博主ID:代码小豪


文章目录

    • list
      • 成员类型
      • 构造、析构、与赋值
      • iterator
      • 元素访问
      • 修改元素
      • list的操作

list

list的数据结构是一个链表,准确的说应该是一个双向链表。这是一个双向链表的节点结构:
在这里插入图片描述
list的使用方式和vector大差不差,区别主要还是体现在某些操作的效率方面,如下:

listvector
插入与删除O(1)O(N)
遍历O(N)O(N)
访问O(N)O(1)

总体而言,如果线性表需要大量的删除和插入,那么使用list会更加高效,如果只是单纯的存储数据,vector比list更好用,而且vector的空间还比list小。

OK,话不多说,开始看看list都有什么操作。

成员类型

由于STL中的容器都是模板类,因此数据的类型和常见的内置类型肯定不同,了解成员类型可以更好的读懂list的各个函数原型。

list的模板如下:

template < class T, class Alloc = allocator<T> > 
class list;

函数原型常见类型有:

类型作用
value_type模板当中的第一个类型,即T
referencevalue_type类型的引用,即T&
pointervalue_type类型的指针,即T*
size_type代表无符号整型
difference_type代表有符号整型

希望大家能记住以上类型,因为接下来的list的函数原型经常会出现上述类型的参数。

构造、析构、与赋值

由于博主也不太会使allocator,因此介绍使用list的时候,参数一律使用alloc的缺省值。

default (1)	
explicit list (const allocator_type& alloc = allocator_type());
fill (2)	
explicit list (size_type n, const value_type& val = value_type(),
                const allocator_type& alloc = allocator_type());
range (3)	
template <class InputIterator>
  list (InputIterator first, InputIterator last,
         const allocator_type& alloc = allocator_type());
copy (4)	
list (const list& x);
  1. default构造:初始化时不传入任何参数,就能实例化出一个空链表。
	list<int> L1;//实例化一个容纳int变量的空链表
	list<float> L2;//实例化一个容纳int变量的空链表
	list<string>L3;//实例化一个容纳string对象的空链表
  1. 填充(fill)构造:构造一个n个值为val的对象的链表。
	list<int>L4(4, 2);//{2,2,2,2}
	list<float>L5(5, 3.14);//{ 3.14, 3.14, 3.14, 3.14, 3.14}
	list<string>L6(2, "hello world");
	//{"hello world","hello world"}
  1. c++11标准还支持使用initializer_list初始化。
list (initializer_list<value_type> il,
       const allocator_type& alloc = allocator_type());

这种初始化方式非常方便,非常好用。关于initializer_list的介绍可以去看看博主的c++杂谈系列。

使用方法大致如下:

	list<int>L7{ 1,2,3,4,5 };//{1,2,3,4,5}
	list<string>L8{ "haha","hehe","xixi"};//{"haha","hehe","xixi"}

是不是有点像给数组初始化时的用法,非常方便。

  1. 范围(range)构造

这种该构造是通过使用传入迭代器的方式,将迭代器内的元素传入list容器当中。

list<int>L7{ 1,2,3,4,5 };//{1,2,3,4,5}
list<string>L8{ "haha","hehe","xixi"};//{"haha","hehe","xixi"}
list<int>L9(L7.begin(), L7.end());//{1,2,3,4,5}
list<string>L9(L8.begin(), L8.end());//{"haha","hehe","xixi"}

当然了,这里的迭代器可以是与list<T>相同类型的迭代器。比如这种用法也是合理的。

	string str("hello world");
	list<char>L11(str.begin(), str.end());
	//{'h','e','l','l','o',' ','w','o','r','d'}

当然了,上面的说法是存在严重错误的,list<char>和string::iterator的类型当然是不一样的,只是读起来顺口而已。实际上我想表达的是:list<char>容器的元素类型是char,而string::iterator指向的元素也是char类型。因此可以这样构造。

  1. 拷贝(copy)构造,构造一个与x一致的容器。
list<int>L12{ 1,2,3,4,5 };
list<int>L13(L12);//L13与L12一致

赋值运算符重载和拷贝构造的使用方法完全一致

 list& operator= (const list& x);
	list<int> list1{ 1,2,3,4 };
	list<int>list2;
	list2 = list1;//list2与list1一致

至于析构函数则没什么需要大家操作的地方了,当list超出作用域时,会自动调用list的析构函数。而且list析构函数还不需要传入参数

iterator

list的迭代器也是分为四种,分别是

(1)正向迭代器
(2)正向定值迭代器
(3)反向迭代器
(4)反向定值迭代器

STL的迭代器用法基本差不多,这里博主就不多演示怎么使用了,大家可以参考vector和string的迭代器用法。

list迭代器的不同之处在于,vector和string的迭代器都是随机迭代器(random access iterator),而list是双向迭代器(bidirectional iterator),随机迭代器可以支持++,–,以及加减算术的操作,而双向迭代器只能使用++或者–操作。

list<int>list1{ 1,2,3,4,5,6 };
list<int>::iterator it = list1.begin();
it + 1;//error,双向迭代器不支持算术加减
it++;//ok,双向迭代器支持自加自减

这意味着我们可以通过一下两种方式遍历list1.

list<int>list1{ 1,2,3,4,5,6 };
list<int>::iterator it = list1.begin();

while (it != list1.end())
{
	cout << *it;
	it++;
}

for (auto& e : list1)
{
	cout << e;
}

元素访问

list不支持使用下标访问符([])访问容器内的元素了。实际上,list一共就提供了两个函数,一个front,一个back。用来访问第一个或者最后一个元素。

reference front();
const_reference front() const;
reference back();
const_reference back() const;
list1.front() = 7;//第一个元素1修改成7
list1.back() = 1;//最后一个元素修改成1

修改元素

大家看看list关于修改元素的函数结口,是不是感觉很熟悉
在这里插入图片描述
可以发现list和vector关于修改元素的函数接口简直是如出一辙、

这是因为Victor,string,list都是线性表的结构,因此对元素的修改操作的效果都是一致的,区别只在于涉及的算法不同,这里我打算将算法放在list的模拟实现当中讲解,或者也可以去看博主的C语言数据结构关于双链表的博客。

list的操作

list和vector虽然在逻辑上是一致的,但是在内存结构上却完全不同了,因此list可执行的操作和vector是不同的。

在这里插入图片描述

  1. remove——移除所有值为val的节点
void remove (const value_type& val);
  1. unique——去掉链表中所有的重复元素。(链表需有序)
	list<int>list2{ 5,6,3,2,1,1,5 };
	list2.sort();//排序
	list2.unique();
	//list2={1,2,3,5,6}
  1. sort——排序
(1)	
  void sort();
(2)	
template <class Compare>
  void sort (Compare comp);

默认情况下会将链表排成升序,如果想要将链表排成降序,就需要用到仿函数(像函数一样使用的类)。

	list<int>list2{ 5,6,3,2,1,1,5 };
	list2.sort();//升序
	for (auto& e : list2)
	{
		cout << e << ' ';
	}
	cout << endl;
	list2.sort(greater<int>());
	//降序,这个greater是一个仿函数模板,博主不做说明
	for (auto& e : list2)
	{
		cout << e << ' ';
	}
  1. reverse——逆置链表
void reverse();

reverse可以让链表中的所有元素的顺序颠倒过来。

  1. merge——合并链表
(1)	
  void merge (list& x);
(2)	
template <class Compare>
  void merge (list& x, Compare comp);

(1)
list容器将与x合并,merge会将x的所有成员都转移到list容器当中。(x会变成一个空链表,而list则会变大)。合并的两个链表必须拥有相同的顺序(升序,不能是逆序)。合并后的链表也会呈升序

list<int>list4{6,5,5,3,5};
	list<int>list5{ 7,9,3,4,2 };
	list4.sort();//list4排成升序
	list5.sort();//list5排成升序
	list4.merge(list5);//将list5和list4合并
	for (auto& e : list4)
	{
		cout << e << ' ';//{2,3,3,4,5,5,5,6,7,9}
	}

(2)
如果我们想要让合并后的链表是逆序的,那就将待合并的链表排成逆序,再传入仿函数comp,可以让合并后的链表呈逆序。

list<int>list4{6,5,5,3,5};
	list<int>list5{ 7,9,3,4,2 };
	list4.sort(greater<int>());//排成逆序
	list5.sort(greater<int>());//排成逆序
	list4.merge(list5,greater<int>());//合并成逆序
	for (auto& e : list4)
	{
		cout << e << ' ';//{9,7,6,5,5,5,4,3,3,2}
	}
  1. splice——粘接(感觉像是剪切)
entire list (1)	
void splice (iterator position, list& x);
single element (2)	
void splice (iterator position, list& x, iterator i);
element range (3)	
void splice (iterator position, list& x, iterator first, iterator last);

splice重载了三个版本,每个版本都有不一样的效果

第一版:全部粘接,将x的全部元素粘接到list容器的迭代器指向的位置。x会变成一个空链表。

	list<int>list1{ 1,2,3,4 };
	list<int>list2{ 10,20,30,40 };
	list1.splice(list1.begin(), list2);
	for (auto& e : list1)
	{
		cout << e << ' '; //{10, 20, 30, 40, 1, 2, 3, 4};
	}

第二版,单元素粘接,将x中的迭代器i指向的元素粘接到容器position指向的位置。

	list<int>list1{ 1,2,3,4 };
	list<int>list2{ 10,20,30,40 };
	list1.splice(list1.begin(), list2,list2.begin());
	for (auto& e : list1)
	{
		cout << e << ' '; //{10,1, 2, 3, 4};
	}

第三版,迭代区间粘接。将x中[first,last)区间内的所有元素都粘接到list容器的position位置上。

	list<int>list1{ 1,2,3,4 };
	list<int>list2{ 10,20,30,40 };
	list1.splice(++list1.begin(), list2,++list2.begin(),--list2.end());
	for (auto& e : list1)
	{
		cout << e << ' '; //{1,20,30 2, 3, 4};
	}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于学习Go语言的并发编程

开始之前&#xff0c;介绍一下​最近很火的开源技术&#xff0c;低代码。 作为一种软件开发技术逐渐进入了人们的视角里&#xff0c;它利用自身独特的优势占领市场一角——让使用者可以通过可视化的方式&#xff0c;以更少的编码&#xff0c;更快速地构建和交付应用软件&#…

Capture One Studio for Mac:打造完美影像的利器

对于摄影师而言&#xff0c;每一次按下快门都是一次对完美影像的追求。而Capture One Studio for Mac正是这样一款能够帮助你实现这一追求的利器。 Capture One Studio for Mac v16.4.2.1中文直装版下载 首先&#xff0c;Capture One Studio for Mac拥有出色的图像处理能力。它…

java项目之人事系统源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的人事系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于vue的人事系统的主要使用者…

独享IP是原生IP吗?

原生IP&#xff1a; 原生IP是指由Internet服务提供商&#xff08;ISP&#xff09;直接分配给用户的IP地址&#xff0c;这些IP地址通常反映了用户的实际地理位置和网络连接。原生IP是用户在其所在地区或国家使用的真实IP地址&#xff0c;与用户的物理位置直接相关。在跨境电商中…

C++奇迹之旅:vector使用方法以及操作技巧

文章目录 &#x1f4dd;前言&#x1f320; 熟悉vector&#x1f309;使用vector &#x1f320;构造函数&#x1f309;vector遍历 &#x1f320;operator[]&#x1f309;迭代器 &#x1f320;Capacity容量操作&#x1f309; size()&#x1f309; capacity()&#x1f309;resize()…

【Android开发】Android请求出现网络请求失败,HTTP请求,安全网络通信与权限管理

额外权限 要有这个权限&#xff1a; <uses-permission android:name"android.permission.INTERNET" />HTTP安全考虑 从 Android 9&#xff08;API 级别 28&#xff09;开始&#xff0c;默认情况下不支持通过 HTTP 访问网络&#xff0c;而要求使用 HTTPS。这…

html 字体设置 (web端字体设置)

windows自带的字体是有版权的&#xff0c;包括微软雅黑&#xff08;方正&#xff09;、宋体&#xff08;中易&#xff09;、黑体&#xff08;中易&#xff09;等 版权算是个大坑&#xff0c;所谓为了避免版权问题&#xff0c;全部使用开源字体即可 我这里选择的是思源宋体&…

软考-下午题-试题二、三

主要是最后一问的不同解答 1、父图子图平衡 1、员工关系是否存在传递依赖&#xff1f;用100字以内的文字说明理由。2019 2、在职员关系模式中&#xff0c;假设每个职员有多名家属成员&#xff0c;那么职员关系模式存在什么问题&#xff1f; 应如何解决&#xff1f;2020 职员关系…

world machine学习笔记(3)

打开 可以打开场景设置&#xff0c;项目设置平铺构建设置 场景设置&#xff1a; 输出范围 设置中心点和范围 设置分辨率 项目设置&#xff1a; 设置地图颜色&#xff0c;单位&#xff0c;最高地形高度 点击这个图形进行预览设置 该按钮还有其他的功能 world machine基础流程…

【成都站线下会议|EI稳定检索|SPIE出版】第三届信号处理与通信安全国际学术会议(ICSPCS 2024)

【SPIE独立出版|确定ISSN、ISBN号&#xff01;&#xff01;】【成都站&#xff01;&#xff01;欢迎投稿参会】 第三届信号处理与通信安全国际学术会议&#xff08;ICSPCS 2024&#xff09; 2024 3rd International Conference on Signal Processing and Communication Secur…

AJAX初级

AJAX的概念&#xff1a; 使用浏览器的 XMLHttpRequest 对象 与服务器通信 浏览器网页中&#xff0c;使用 AJAX技术&#xff08;XHR对象&#xff09;发起获取省份列表数据的请求&#xff0c;服务器代码响应准备好的省份列表数据给前端&#xff0c;前端拿到数据数组以后&#xf…

设计新境界:大数据赋能UI的创新美学

设计新境界&#xff1a;大数据赋能UI的创新美学 引言 随着大数据技术的蓬勃发展&#xff0c;它已成为推动UI设计创新的重要力量。大数据不仅为界面设计提供了丰富的数据资源&#xff0c;还赋予了设计师以全新的视角和工具来探索美学的新境界。本文将探讨大数据如何赋能UI设计…

云部署最简单python web

最近在玩云主机&#xff0c;考虑将简单的web应用装上去&#xff0c;通过广域网访问一下&#xff0c;代码很简单&#xff0c;所以新手几乎不会碰到什么问题。 from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return Hello, World!app.route(/gree…

力扣 滑动窗口题目总结

Leetcode3.无重复字符的最长子串 思路&#xff1a; 这道题主要用到思路是&#xff1a;滑动窗口 什么是滑动窗口&#xff1f; 其实就是一个队列,比如例题中的 abcabcbb&#xff0c;进入这个队列&#xff08;窗口&#xff09;为 abc 满足题目要求&#xff0c;当再进入 a&#x…

2024年上半年软件系统架构师论文【回忆版】

文章目录 考试时间考试地点案例分析1、微服务架构的优点和缺点2、质量属性的6个元素3、分布式锁 Redis的缺点4、MongoDB 存储矢量图的优势 论文回忆版论文一、论单元测试的设计与应用论文二、论大数据模型的设计与应用论文三、论模型驱动的架构设计及应用论文四、论云原生运维的…

LeetCode 279 —— 完全平方数

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 此图利用动态规划进行求解&#xff0c;首先&#xff0c;我们求出小于 n n n 的所有完全平方数&#xff0c;存放在数组 squareNums 中。 定义 dp[n] 为和为 n n n 的完全平方数的最小数量&#xff0c;那么有状态…

esp32-idf 开发踩坑记录

现象 直接使用原始命令编译idf.py build 但是提示idf 版本错误 卸载旧版本 编译出错build 问题 然后删除编译文件后&#xff0c;重新编译&#xff0c;还是出错 解决方法1 最后发现是因为项目所在文件夹有中文目录&#xff0c;把项目迁移到英文目录后&#xff0c;重新编译&a…

【Python 对接QQ的接口(二)】简单用接口查询【等级/昵称/头像/Q龄/当天在线时长/下一个等级升级需多少天】

文章日期&#xff1a;2024.05.25 使用工具&#xff1a;Python 类型&#xff1a;QQ接口 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解密处理&#xff08;直接解密即可&#xff09;&#xff08;crypto-js.js 标准算法&#xff09;&…

同名在线查询系统微信小程序源码下载支持多种流量主,附带系统教程

同名在线查询系统微信小程序源码下载支持多种流量主这是一款支持查询同名的一款微信小程序 该款小程序支持多种查询模式 重名查询&#xff0c;热度查询&#xff0c;概率香查询 源码免费下载地址抄笔记(chaobiji.cn)

arcgisPro将一个图层的要素复制到另一个图层

1、打开两个图层&#xff0c;如下&#xff0c;其中一个图层中有两个要素&#xff0c;需要将其中一个要素复制到另一个图层中&#xff0c;展示如下&#xff1a; 2、选中待复制要素&#xff0c;点击复制按钮&#xff0c;如下&#xff1a; 3、下拉粘贴按钮列表&#xff0c;选择【选…