【C++标准模版库】list的介绍及使用

list

  • 一.list的介绍
  • 二.list的使用
    • 1.list 构造函数
    • 2.list 空间大小
    • 3.list 增删查改
    • 4.list 迭代器的使用
      • 1.正向迭代器
      • 2.反向迭代器
    • 5.list 其他成员函数
  • 三.vector与list关于sort性能的比较

一.list的介绍

  C++中的list标准模板库(STL)是C++标准库中的一个重要组成部分,它提供了一种双向链表的数据结构实现。list是C++ STL中的一个序列容器,它允许在常数时间内进行任意位置的插入和删除操作。与vector不同,list是一个双向链表,其元素不是连续存储的,而是存储在互不相关的独立节点中,每个节点都包含数据部分和两个指针(分别指向前一个节点和后一个节点)。

list关键特性:

  1. 双向链表:list的底层实现是双向链表,支持高效的插入和删除操作,尤其是在链表的头部和尾部。
  2. 不支持随机访问:与vector和deque(双向队列)等容器不同,list不支持通过索引直接访问元素,访问特定位置的元素需要从已知位置(如头部或尾部)开始迭代。
  3. 迭代器:list提供了双向迭代器,允许从前往后或从后往前遍历链表。
  4. 内存分配:由于list的元素不是连续存储的,因此它不需要在插入或删除元素时重新分配大块内存,这减少了内存碎片和重新分配的开销。

二.list的使用

  学习list时查看文档是非常重要的(list的文档介绍),list在实际中非常的重要,在实际中我们熟悉常见的接口就可以,下面列出了哪些接口是要重点掌握的。

1.list 构造函数

(construct)构造函数声明接口说明
list()(重点)无参构造
list(size_type n, const value_type& val =value_type())构造并初始化n个val,无val默认为T(),例如整形为0
list (const list& x)(重点)拷贝构造
list (InputIterator first, InputIterator last)使用迭代器区间进行初始化构造

注意:list使用模板,template < class T > ,其中将T重定义为value_type。

int main()
{list<int> l1; //无参构造list<int> l2(10, 1); //10个1有参构造list<int> l3(l2.begin(), l2.end()); //迭代器区间构造list<int> l4(l2); //拷贝构造//list<int> l3(l2.begin() + 3, l2.end() - 2); errorlist<int> l5(++l2.begin(), --l2.end()); //注意:list迭代器区间构造不支持+,-操作,但是支持++,--//1.迭代器循环遍历list<int>::iterator it = l4.begin();while (it != l4.end()){cout << *it << " ";++it;}cout << endl;//2.auto+范围for变量for (auto e : l4){cout << e << " ";}cout << endl;return 0;
}

2.list 空间大小

函数声明接口说明
size返回list中有效节点的个数
empty检测list是否为空,是返回true,否则返回false
int main()
{list<int> l1;cout << l1.size() << endl;  //0cout << l1.empty() << endl; //1return 0;
}

3.list 增删查改

函数声明接口声明
front返回list的第一个节点中值的引用
back返回list的最后一个节点中值的引用
push_front在list首元素前插入值为val的元素
pop_front删除list中第一个元素
push_back在list尾部插入值为val的元素
pop_back删除list中最后一个元素
assign赋值:支持个数赋值、迭代器赋值(不常用)
insert在list position 位置中插入值为val的元素(只支持迭代器)
erase删除list position位置的元素(只支持迭代器)
swap交换两个list中的元素
resize改变list的有效元素的个数
clear清空list中的有效元素
emplace_front在某些情况下比push_front效率高
emplace_back在某些情况下比push_back效率高
int main()
{list<int> l1(10, 1); //初始化为10个1l1.front() = 100; //返回引用——>修改头为100l1.back() = 100;  //返回引用——>修改尾为100l1.push_front(10); //头插l1.pop_front();    //头删l1.push_back(10);  //尾插l1.pop_back();     //尾删list<int> l2;l2.assign(5, 1); //赋值为5个1l2.assign(l1.begin(), l1.end()); //迭代器赋值list<int> l3;l3.push_back(1);l3.push_back(2);l3.push_back(3);l3.push_back(4);//要求在第3个位置插入10:实际是第四个位置变成10//错误写法:l3.insert(l3.begin() + 3, 10); //双向迭代器:支持++/--、不支持随机访问+/-//正确写法如下:auto it = l3.begin();int k = 3;while (k--){++it;}l3.insert(it, 10); //插入一个10for (auto e : l3){cout << e << " "; //1 2 3 10 4}cout << endl;l3.insert(it, 5, 1); //插入5个1for (auto e : l3){cout << e << " "; //1 2 3 10 4}cout << endl;l3.insert(it, l1.begin(), l1.end()); //插入5个1for (auto e : l3){cout << e << " "; //1 2 3 10 4}cout << endl;int x = 0;cin >> x;it = find(l3.begin(), l3.end(), x); //先找x所在的迭代器if (it != l3.end()) //找不到x的表面:it == l3.end(){l3.erase(it); //按照迭代器删除x}l3.swap(l1); //l3与l1交换l3.clear();  //清空l3中的有效数据l3.resize(10, 1); //修改有效数据的个数:10个数据全为1l3.resize(20);    //前10个数据全为1,后10个数据默认为0return 0;
}
struct A
{
public:A(int a1 = 1, int a2 = 1):_a1(a1), _a2(a2){cout << "A(int a1 = 1, int a2 = 1)" << endl;}A(const A& a){cout << "A(const A& a)" << endl;}int _a1;int _a2;
};
int main()
{//对于内置类型无区别list<int> l1;l1.push_back(1);l1.emplace_back(2);list<A> l2;A aa1(1, 1);l2.push_back(aa1);     //尾插有名对象l2.push_back(A(2, 2)); //尾插匿名对象//l2.push_back(3, 3);  //不支持A aa2(1, 1); //有参构造l2.emplace_back(aa2); //拷贝构造l2.emplace_back(A(2, 2)); //有参构造+拷贝构造//emplace_back()支持直接传构造A对象的参数,而push_back()不支持l2.emplace_back(3, 3); //直接有参构造更高效return 0;
}

在这里插入图片描述

4.list 迭代器的使用

函数声明接口说明
begin + end(重点)获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator
rbegin + rend获取最后一个数据位置的reverse_iterator/const_reverse_iterator,获取第一个数据前一个位置的reverse_iterator/const_reverse_iterator

迭代器划分为两类:

按照功能:

  1. 正向迭代器:iterator
  2. 反向迭代器:reverse_iterator
  3. const修饰正向迭代器:const_iterator
  4. const修饰反向迭代器:const_reverse_iterator

按照性质:

  1. 单向:forward_list/unordered_map… 支持:++
  2. 双向:list/map/set… 支持:++/–
  3. 随机:vector/string/deque… 支持:++/–/+/-

+:正向、支持随机访问(例如:支持begin()++、begin() + 3)
-:反向、支持随机访问(例如:支持begin()- -、begin() - 3)
++:正向、不支持随机访问(例如:支持begin()++、不支持begin() + 3)
–:反向、不支持随机访问(例如:支持begin()- -、不支持begin() - 3)

双向包含单向,同理随机包含双向。

在这里插入图片描述

int main()
{list<int> l1(10, 1);//list不支持算法库中的sort,要求随机迭代器//sort(l1.begin(), l1.end());//vector、string支持sortstring s1("156874239");sort(s1.begin(), s1.end());cout << s1 << endl; //123456789return 0;
}

1.正向迭代器

在这里插入图片描述

int main()
{//普通正向迭代器list<int> l1(10, 1);list<int>::iterator it = l1.begin();while (it != l1.end()){//(*it)++; 可以修改cout << *it << " ";++it;}cout << endl;//const修饰正向迭代器const list<int> l2(10, 1);list<int>::const_iterator cit = l2.begin();while (cit != l2.end()){//(*cit)++; 不可以修改cout << *cit << " ";++cit;}cout << endl;return 0;
}

2.反向迭代器

在这里插入图片描述

int main()
{//普通反向迭代器list<int> l1(10, 1);list<int>::reverse_iterator rit = l1.rbegin();while (rit != l1.rend()){//(*rit)++; 可以修改cout << *rit << " ";++rit;}cout << endl;//const修饰反向迭代器const list<int> l2(10, 1);list<int>::const_reverse_iterator crit = l2.rbegin();while (crit != l2.rend()){//(*crit)++; 不可以修改cout << *crit << " ";++crit;}cout << endl;return 0;
}

5.list 其他成员函数

函数声明接口声明
reverse逆置设计的些许冗余,可以使用算法库中的reverse
sort排序:默认得到升序的list,降序需要使用仿函数
merge合并两个有序的list,默认传入升序的list,得到升序的list,降序需要使用仿函数
unique将有序的list去除重复的数据
remove移除给定值的数据
splice剪切+粘贴(具体看如下代码)
int main()
{list<int> l1;l1.push_back(1);l1.push_back(2);l1.push_back(3);l1.push_back(4);//list的成员函数reverse设计的有些冗余l1.reverse();//算法库的reversereverse(l1.begin(), l1.end());l1.sort(); //排序:默认升序,低层是归并//算法库的函数sort要支持随机访问,无法被list使用,低层是快排//降序——>仿函数less<int> ls;    //小于号:升序greater<int> gt; //大于号:降序l1.sort(ls);l1.sort(greater<int>()); //匿名对象list<int> first;first.push_back(1);first.push_back(3);first.push_back(5);list<int> second;second.push_back(2);second.push_back(4);second.push_back(6);//合并两个升序list,得到升序的list,此时second为空//也支持合并两个降序list,得到降序的list——>与sort一样使用仿函数first.merge(second); cout << first.size() << endl;  //6cout << second.size() << endl; //0list<int> l2;l2.push_back(1);l2.push_back(3);l2.push_back(2);l2.push_back(2);l2.push_back(5);l2.push_back(5);l2.sort();    //先排序再去重l2.unique();  //有序list去重l2.remove(3); //移除3return 0;
}
int main()
{list<int> mylist1, mylist2;for (int i = 1; i <= 4; ++i){ mylist1.push_back(i);      //mylist1: 1 2 3 4}for (int i = 1; i <= 3; ++i){mylist2.push_back(i * 10); //mylist2: 10 20 30}list<int>::iterator it;it = mylist1.begin();++it;//一个链表的节点转移给另一个链表mylist1.splice(it, mylist2); //mylist1:1 10 20 30 2 3 4//mylist2:emptylist<int> l1;l1.push_back(1);l1.push_back(2);l1.push_back(3);l1.push_back(4);l1.push_back(5);l1.push_back(6);int x;cin >> x;it = find(l1.begin(), l1.end(), x);if (it != l1.end()){//l1.splice(l1.begin(), l1, it); //将it位置的数据剪切粘贴到l1的头部//将迭代器区间it~l1.end()剪切粘贴到l1的头部l1.splice(l1.begin(), l1, it, l1.end()); }return 0;
}

三.vector与list关于sort性能的比较

注意:凡是测试性能Debug下不具有参考价值,要在release下测试性能。

int main()
{srand(time(0));const int N = 1000000;list<int> l1;vector<int> v1;for (int i = 0; i < N; ++i){auto e = rand() + i; //减少重复的数值l1.push_back(e);v1.push_back(e);}int begin1 = clock();sort(v1.begin(), v1.end()); //算法库:sort(快排)排序vectorint end1 = clock();int begin2 = clock();l1.sort(); //无法使用算法库的sort,使用类成员函数sort(归并)排序int end2 = clock();printf("vector sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);return 0;
}

在这里插入图片描述

思考:可以发现算法库中的sotr性能更高,list中成员函数sort性能不太高,因此如果将list中的数据拷贝到vector中进行sort,再将vector赋值到list时性能还会更高?代码如下:

int main()
{srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;for (int i = 0; i < N; ++i){auto e = rand() + i;lt1.push_back(e);lt2.push_back(e);}int begin1 = clock();//拷贝vectorvector<int> v(lt2.begin(), lt2.end());//排序sort(v.begin(), v.end());//拷贝回lt2lt2.assign(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf("list copy vector sort copy list sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}

在这里插入图片描述

事实证明:拷贝数据不会花太多时间,以及list排序性能不太行,甚至不如拷贝到vector中进行排序。

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

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

相关文章

PCL1.11.0下载安装(Windows)

PCL1.11.0下载安装&#xff08;Windows&#xff09; PCL安装需要的几个模块如下图所示&#xff1a; 一、PCL1.11.0下载 PCL以1.11.0版本为例&#xff0c;打开下载连接&#xff08;PCL下载&#xff09; 下载PCL-1.11.0-AllInOne-msvc2019-win64.exe和pcl-1.11.0-pdb-msvc2019-…

Vue3 列表自动滚动播放(表头固定、列表内容自动滚动播放)+ vue3-seamless-scroll - 附完整示例

vue3-seamless-scroll&#xff1a;Vue3.0 无缝滚动组件&#xff0c;支持Vite2.0&#xff0c;支持服务端打包 目前组件支持上下左右无缝滚动&#xff0c;单步滚动&#xff0c;并且支持复杂图标的无缝滚动&#xff0c;目前组件支持平台与Vue3.0支持平台一致。 目录 效果 一、介绍…

腾讯云AI代码助手评测:如何智能高效完成Go语言Web项目开发

腾讯云AI代码助手评测&#xff1a;如何智能高效完成Go语言Web项目开发 &#x1f680; 文章目录 腾讯云AI代码助手评测&#xff1a;如何智能高效完成Go语言Web项目开发 &#x1f680;背景引言开发环境介绍腾讯云AI代码助手使用实例1. 代码补全2. 技术对话3. 代码优化4. 规范代码…

(计算机网络)物理层

目录 一.基本概念 二.基本术语 三.码元 四.多路复用技术 一.基本概念 1. 2. 3. 4. 5. 6. 7. 8. 9. 二.基本术语 1. 2. 3.早期--公用的电话网传输数据&#xff0c;网络上传的是模拟信号&#xff0c;调制解调器--将数字信号转化成模拟信号&#xff0c;最后&#xff0c;调制解…

NSSCTF-GDOUCTF 2023新生赛

[GDOUCTF 2023]hate eat snake 考察&#xff1a;js代码审计 打开题目&#xff0c;发现需要坚持60秒&#xff0c;那么简单的一个思路就是修改得分的变量>60即可 办法1&#xff1a;修改变量 右键查看源代码&#xff0c;之后发现有一个snake.js的文件&#xff0c;ctrlf搜索i…

程序设计基础(c语言)_补充_1

1、编程应用双层循环输出九九乘法表 #include <stdio.h> #include <stdlib.h> int main() {int i,j;for(i1;i<9;i){for(j1;j<i;j)if(ji)printf("%d*%d%d",j,i,j*i);elseprintf("%d*%d%-2d ",j,i,j*i);printf("\n");}return 0…

DS18B20数字温度传感器操作解析

文章目录 引言特点工作原理引脚说明配置寄存器温度寄存器时序初始化时序写时序读时序 引言 DS18B20 是一种广泛使用的数字温度传感器&#xff0c;具有高精度和易用性。是Dallas Semiconductor公司&#xff08;现为Maxim Integrated公司&#xff09;生产的单总线数字温度传感器…

关爱提示器-不要久坐

关爱提示器-不要久坐 最近身体不适腰疼脖子疼的&#xff0c;去医院检查&#xff0c;大夫提示注意身体不要久坐多运动等等之类的&#xff0c;哎&#xff0c;生活所迫&#xff0c;披星戴月兢兢业业的&#xff0c;到头来还要被批判躺平不努力。哎&#xff0c;先关爱自己吧&#xf…

Java | Leetcode Java题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; public class Solution {public int coinChange(int[] coins, int amount) {int max amount 1;int[] dp new int[amount 1];Arrays.fill(dp, max);dp[0] 0;for (int i 1; i < amount; i) {for (int j 0; j < coins.length; j)…

Dynamo修改共享参数绑定的分组——群问题整理005

Hello大家好!我是九哥~ 今天继续给大家分享一些短平快的小教程,是来自群里面的问题。 问题005:Dynamo修改共享参数绑定的分组 今天看到群里询问如何修改参数所在的分组,查了下API,项目参数是不行的,不过共享参数是允许ReInsert()的,那么就好办了。 然后在Document下…

JavaEE 第4节 线程安全问题

小贴士&#xff1a; 本节题目所述的主题其实非常的庞大&#xff0c;如果要细讲起来&#xff0c;一篇博客远远不够&#xff0c;本篇博客只会每个方面的内容做一个简要描述&#xff0c;详细的内容在后续同专栏博客中都会涉及到的&#xff0c;如果有需要可以一步到本专栏的其他博客…

python运行js之execjs基本使用

python运行js之execjs基本使用 现在大部分网站都使用JS加密和JS加载的情况&#xff0c;数据并不能直接被抓取出来&#xff0c;这时候就需要使用第三方类库来执行JS语句。 官网&#xff1a;https://pypi.org/project/PyExecJS/ 使用前提&#xff1a;电脑需要安装 Node.js 一、安…

最新口型同步技术EchoMimic部署

EchoMimic是由蚂蚁集团推出的一个 AI 驱动的口型同步技术项目&#xff0c;能够通过人像面部特征和音频来帮助人物“对口型”&#xff0c;生成逼真的动态肖像视频。 EchoMimic的技术亮点在于其创新的动画生成方法&#xff0c;它不仅能够通过音频和面部关键点单独驱动图像动画&a…

【星闪开发连载】WS63E 星闪开发板和hi3861开发板的对比

此次星闪开发者体验官活动使用的开发板都是NearLink_DK_WS63E开发板&#xff0c;它和NearLink_DK_WS63开发板的区别在于具有雷达感知功能。从开发板的照片也可以看到WS63E有一个雷达天线接口。 我们把WS63E开发板和hi3861开发板的功能做了简单的对比&#xff0c;见下表。 参数…

用户看广告获取密码访问网页内容流量主模式源码

简介&#xff1a; 全开源付费进群流量主模式&#xff0c;用户看广告获取密码访问网页内容&#xff0c;网站生成内容&#xff0c;用户需要浏览内容跳转至小程序&#xff0c;观看广告后获取密码&#xff0c;输入密码查看网页内容。 与之前得9.9付费进群区别就是内容体现在了网页…

iPhone苹果手机Safari浏览器怎么收藏网页?

iPhone苹果手机Safari浏览器怎么收藏网页? 1、iPhone苹果手机上找到并打开Safari浏览器&#xff0c;并访问要收藏的网页&#xff1b; 2、打开网页后&#xff0c;点击导航上的更多功能&#xff1b; 3、在更多里&#xff0c;找到并点击添加到个人收藏&#xff0c;完成储存即可添…

JavaSE面试篇章——一文干破Java集合

文章目录 Java集合——一文干破集合一、集合的理解和好处1.1 数组1.2 集合 二、集合的框架体系三、Collection接口和常用方法3.1 Collection接口实现类的特点3.2 Collection接口遍历元素方式1-使用Iterator(迭代器)3.2.1 基本介绍3.2.2 迭代器的执行原理3.2.3 Iterator接口的方…

java基础 之 equals和==的区别

文章目录 浅谈“”特点比较基本类型比较引用类型 浅谈“equals”背景和使用重写equals自定义类为什么需要重写equals方法 总结附录代码及文章推荐 前言&#xff1a; 1、8大基本数据类型&#xff0c;它们的值直接代表了某种数据&#xff0c;不是对象的实例&#xff0c;不能使用n…

关于企微群聊天工具功能的开发---PHP+JS+CSS+layui (手把手教学)

文章目录 前言准备工作PHP代码示例前端代码示例 主要是js踩的小坑&笔记最终达成的效果总结 前言 公司要求开发企微群聊天工具。首先一个客户一个群&#xff0c;其余群成员都是公司销售、设计师、工长、售后等人员。要求开发一个群聊天工具&#xff0c;工长点击进来以后就可…

ReentrantLock源码分析

文章目录 一、AQS1、state属性2、等待队列3、条件变量 二、ReentrantLock1、非公平锁实现原理1.1 获取锁1.2 释放锁1.3 可重入原理1.4 可打断原理不可打断可打断 1.5 公平锁实现原理1.6 条件变量原理awaitsignal 一、AQS AQS全称是 AbstractQueuedSynchronizer&#xff0c;是阻…