C++系列-STL容器之list

STL容器之list

  • list容器的基本结构
  • list容器的特点
    • list容器的优点
    • list容器的缺点
  • list容器的构造函数
  • list容器的常用接口
    • list赋值操作
    • list大小及空否
    • list访问
    • list迭代器相关
    • list增删查改
      • push and pop
      • insert
      • 其它


寄扬州韩绰判官
杜牧〔唐代〕

青山隐隐水迢迢,秋尽江南草未凋。
二十四桥明月夜,玉人何处教吹箫?


list容器的基本结构

list容器的内部结构是双向循环链表,主要由一系列的节点组成,每个节点包含3个部分

  • 数据域:存储实际的元素值。
  • 前向指针:指向链表中的前一个节点。
  • 后向指针:指向链表中的后一个节点。
  • 整个list通过这些节点的指针指向互相连接,形成一个有序的序列。头节点不放实际数据,只放下一个节点的指针。
  • 每个节点中的previous指针指向前一个节点,next指针指向后一个节点。最后一个节点的next指向头节点,头节点的previous指针最后一个节点。
    在这里插入图片描述

list容器的特点

list容器的优点

  • 采用动态存储分配,内存分配更灵活,不会造成内存的浪费和溢出。
  • 执行插入和删除不需要移动大量的元素,只需要修改节点中的指针,在频繁插入和删除的情况下,高效。
  • 提供反向迭代器,可以方便地从后向前遍历list。
  • 插入操作不会造成原有的list迭代器失效,只是修改了节点中的指针指向关系。
  • 删除操作中指向被删除节点的迭代器会失效,其余的迭代器并不失效。

list容器的缺点

  • 空间(指针域占用空间)和时间(遍历)额外耗费较大,不如vector。
  • 不能支持迭代器任意位置,迭代器计算只支持++或者–。

list容器的构造函数

构造函数说明
list (n, elem)创建的对象中含有n个elem
list{}创建的对象中的内容是花括号中的元素
list ()默认构造,空list
list (const list& x)拷贝构造
list (InputIterator first, InputIterator last)用迭代区间 [first, last) 区间中的元素构造list
code:
#include <iostream>
#include <list>
#include <vector>
using namespace std;template<typename T>
void print_list(const list<T>& lst)
{for (list<int>::const_iterator it = lst.begin(); it != lst.end(); it++)  // 不能<哪个迭代器{cout << *it << " ";	}cout << endl;
}void test01()
{list<int> lst1(5, 10);		// list (n, elem), 创建的对象中含有n个elem cout << "---------- lst1 ----------" << lst1.size() << endl;cout << "lst1.size(): " << lst1.size() << endl;print_list(lst1);list<int> lst2{1, 2, 3};	// list{}, 利用{}创建对象cout << "---------- lst2 ----------" << lst1.size() << endl;print_list(lst2);list<int> lst3(lst2);		// 拷贝构造cout << "---------- lst3 ----------" << lst1.size() << endl;print_list(lst3);list<int> lst4;				// 默认构造lst4.push_back(666);lst4.push_back(888);lst4.push_front(1);cout << "---------- lst4 ----------" << lst4.size() << endl;print_list(lst4);vector<int> v1{ 11, 22, 33, 44, 55 };list<int> lst5(v1.begin(), v1.begin() + 3);	// 迭代区间构造cout << "---------- lst5 ----------" << lst5.size() << endl;print_list(lst5);
}
int main()
{test01();system("pause");return 0;
}result:
---------- lst1 ----------5
lst1.size(): 5
10 10 10 10 10
---------- lst2 ----------5
1 2 3
---------- lst3 ----------5
1 2 3
---------- lst4 ----------3
1 666 888
---------- lst5 ----------3
11 22 33

list容器的常用接口

list赋值操作

形式说明
=重载lst2=lst1
assign({})用初始化列表中的元素替换容器中原有的内容
assign(n elem)用n个elem替换容器中原有的内容
assign(iterator first, iterator last)用[first, last)前闭后开区间的元素替换容器中原有的内容
code:
#include <iostream>
#include <list>
#include <vector>
using namespace std;template<typename T>
void print_list(const list<T>& lst)
{for (typename list<T>::const_iterator it = lst.begin(); it != lst.end(); it++){cout << *it << " ";	// 返回第一个元素}cout << endl;
}
// 在这里存在模板的嵌套,list<T>::const_iterator这个类型就是list模板中的类型,而且嵌套在了模板函数func当中,
// 当实例化func时,vector<T>变成了vector<int>,但是这并不意味着vector已经被实例化了,也就是说当编译器解析
// func时,尚未清楚list到底是什么东西,那么当然也就无法确认list<T>::const_iterator是什么东西了。它可能是
// 一个类型,也可能是static成员。这就会导致歧义出现,编译器无法判断,因此解决方法就是,在嵌套从属类型前面
// 加上typename,告诉编译器这就是一个类型,于是编译器就不会爆出语法错误了。void test01()
{list<int> lst1(5, 10);			// list (n, elem), 创建的对象中含有n个elem cout << "---------- lst1 ----------" << lst1.size() << endl;print_list<int>(lst1);list<int> lst2 = lst1;			// =重载cout << "---------- lst2 ----------" << lst2.size() << endl;print_list(lst2);				// 函数模板自动类型推导list<int> lst3;lst3.assign(5, 666);			// assign(n, elem)cout << "---------- lst3 ----------" << lst3.size() << endl;print_list(lst3);list<char> lst4;				// assign{初始化列表}lst4.assign({'a', 'b', 'c'});cout << "---------- lst4 ----------" << lst4.size() << endl;print_list<char>(lst4);vector<int> vct1{100, 200, 300, 400};list<int> lst5;					lst5.assign(vct1.begin(), vct1.begin()+2);	// assign(iterator first, iterator last)cout << "---------- lst5 ----------" << lst5.size() << endl;print_list(lst5);				// 函数模板自动类型推导
}
int main()
{test01();system("pause");return 0;
}result:
---------- lst1 ----------5
10 10 10 10 10
---------- lst2 ----------5
10 10 10 10 10
---------- lst3 ----------5
666 666 666 666 666
---------- lst4 ----------3
a b c
---------- lst5 ----------2
100 200

list大小及空否

接口函数说明
empty()检测list是否为空,是返回true,否则返回false
size()返回list中有效节点的个数
resize(num)重新指定容器的长度为num,若容器变长,则以默认值填充新位置,若容器变短,则末尾超出原容器长度的元素被删除
resize(num,elem)重新指定容器的长度为num,若容器变长,则以elem填充新位置,若容器变短,则末尾超出原容器长度的元素被删除

list访问

接口函数说明
front()返回list的第一个节点中值的引用
back()返回list的最后一个节点中值的引用

list迭代器相关

接口函数说明
begin()返回指向列表第一个元素的迭代器
end()返回指向列表尾端元素的下一个的迭代器
rbegin()返回指向从反向数的第一个元素的迭代器
rend()返回指向从反向数的尾端元素的下一个的迭代器
code:
#include <iostream>
#include <list>
using namespace std;template<typename T>
void print_list(const list<T>& lst)
{for (typename list<T>::const_iterator it = lst.begin(); it != lst.end(); it++)	// 在模板嵌套中,这里要加上typename 表明T是一个模板参数{cout << *it << " ";}cout << endl;
}void test01()
{list<int> lst1;			if (lst1.empty())			// 判断是否为空{cout << "lst1 is empty!" << endl;}cout << "---------- lst1, lst1.size() ----------" << lst1.size() << endl;	// 有效节点个数lst1.assign({ 1,2,3,4 });								// assign初始化赋值cout << "lst1.assign({ 1,2,3,4 })" << endl;print_list<int>(lst1);cout << "lst1.front(): " << lst1.front() << endl;		// front() 头元素cout << "lst1.back(): " << lst1.back() << endl;			// back() 尾元素cout << "* lst1.begin(): " << *lst1.begin() << endl;	// lst1.begin()迭代器指向第一个元素cout << "* (--lst1.end()): " << *(--lst1.end()) << endl;// lst1.end()迭代器指向末尾元素的下一个,--lst1.end()指向末尾元素cout << "* lst1.rbegin(): " << *lst1.rbegin() << endl;cout << "*(--lst1.rend()): " << *(--lst1.rend()) << endl;// resize(num), 添加默认元素lst1.resize(8);cout << "---------- lst1.resize(8), lst1.size()  ----------" << lst1.size() << endl;print_list<int>(lst1);//resize(num,elem), 添加elem元素lst1.resize(10, 666);cout << "---------- lst1.resize(10, 666)), lst1.size()  ----------" << lst1.size() << endl;print_list<int>(lst1);//resize(num,elem), 添加elem元素lst1.resize(3);cout << "---------- lst1.resize(3), lst1.size()  ----------" << lst1.size() << endl;print_list<int>(lst1);
}
int main()
{test01();system("pause");return 0;
}result:
lst1 is empty!
---------- lst1, lst1.size() ----------0
lst1.assign({ 1,2,3,4 })
1 2 3 4
lst1.front(): 1
lst1.back(): 4
* lst1.begin(): 1
* (--lst1.end()): 4
* lst1.rbegin(): 4
*(--lst1.rend()): 1
---------- lst1.resize(8), lst1.size()  ----------8
1 2 3 4 0 0 0 0
---------- lst1.resize(10, 666)), lst1.size()  ----------10
1 2 3 4 0 0 0 0 666 666
---------- lst1.resize(3), lst1.size()  ----------3
1 2 3

list增删查改

push and pop

接口函数说明
push_front(const T &val)在list首元素前插入值为val的元素
pop_front()删除list中第一个元素
push_back(const T &val)在list尾部插入值为val的元素
pop_back()删除list中最后一个元素

insert

接口函数说明
insert(iterator pos, const T &val)在list position 位置前插入值为val的元素
insert(iterator pos, num, const T &val)在list position 位置前插入值为num个值为val的元素
insert(iterator pos, begin, end)在list position 位置前插入值为num个值为val的元素
code:
#include <iostream>
#include <list>
#include <vector>
using namespace std;template<typename T>
void print_list(const list<T>& lst)
{for (typename list<T>::const_iterator it = lst.begin(); it != lst.end(); it++){cout << *it << " ";	// 返回第一个元素}cout << endl;
}void test01()
{// push pop举例list<string> lst1;lst1.push_back("push_back");cout << "---------- push_back ---------- " << lst1.size() << endl;print_list(lst1);lst1.push_front("push_front");cout << "---------- push_front ---------- " << lst1.size() << endl;print_list(lst1);lst1.pop_back();cout << "---------- pop_back ---------- " << lst1.size() << endl;print_list(lst1);lst1.pop_front();cout << "---------- pop_front, lst1.size() ---------- " << lst1.size() << endl;print_list(lst1);// insert举例list<int> lst2{1, 2, 3, 4, 5, 6};lst2.insert(++lst2.begin(), 222);		// insert(iterator pos, const T &val)cout << "---------- lst2.insert(++lst2.begin(), 222), lst2.size() ---------- " << lst2.size() << endl;print_list(lst2);lst2.insert(--lst2.end(), 3, 666);		// insert(iterator pos, num, const T &val)cout << "---------- lst2.insert(--lst2.end(), 3, 666), lst2.size() ---------- " << lst2.size() << endl;print_list(lst2);vector<int> vec1{11, 22, 33, 44};lst2.insert(lst2.end(), vec1.begin(), vec1.begin() + 3);		// insert(iterator pos, begin, end)cout << "---------- lst2.insert(lst2.end(), vec1.begin(), vec1.begin()+3), lst2.size() ---------- " << lst2.size() << endl;print_list(lst2);// erase举例lst2.erase(++lst2.begin());		// erase(iterator pos)cout << "---------- lst2.erase(++lst2.begin()), lst2.size() ---------- " << lst2.size() << endl;print_list(lst2);
}
int main()
{test01();system("pause");return 0;
}result:
---------- push_back ---------- 1
push_back
---------- push_front ---------- 2
push_front push_back
---------- pop_back ---------- 1
push_front
---------- pop_front, lst1.size() ---------- 0---------- lst2.insert(++lst2.begin(), 222), lst2.size() ---------- 7
1 222 2 3 4 5 6
---------- lst2.insert(--lst2.end(), 3, 666), lst2.size() ---------- 10
1 222 2 3 4 5 666 666 666 6
---------- lst2.insert(lst2.end(), vec1.begin(), vec1.begin()+3), lst2.size() ---------- 13
1 222 2 3 4 5 666 666 666 6 11 22 33
---------- lst2.erase(++lst2.begin()), lst2.size() ---------- 12
1 2 3 4 5 666 666 666 6 11 22 33

其它

接口函数说明
erase(iterator pos)删除list position位置的元素
lst1.swap(lst2)交换两个list中的元素
clear()清空list中的有效元素
remove(const T &val)删除列表中所有指为val的元素
reverse()反转列表
sort()对列表排序
code:
#include <iostream>
#include <list>
using namespace std;template<typename T>
void print_list(const list<T>& lst)
{for (typename list<T>::const_iterator it = lst.begin(); it != lst.end(); it++){cout << *it << " ";	}cout << endl;
}void test01()
{list<int> lst1{1,2,3,4,5,6};list<int> lst2{99, 88, 77, 66};// swap 举例cout << "---------- before swap,lst1, lst2 ---------- " << endl;print_list(lst1);print_list(lst2);cout << "---------- after swap,lst1, lst2 ---------- " << endl;lst1.swap(lst2);print_list(lst1);print_list(lst2);// remove举例cout << "---------- lst2.insert(--(--lst2.end()), 3, 666) ---------- " << endl;lst2.insert(--(--lst2.end()), 3, 666);print_list(lst2);lst2.remove(666);cout << "---------- lst2.remove(666), lst2.size() ---------- " << lst2.size() << endl;print_list(lst2);// reverse举例lst2.reverse();cout << "---------- lst2.reverse() ---------- " << endl;print_list(lst2);// clear举例lst2.clear();cout << "---------- lst2.clear(), lst2.size() ---------- " << lst2.size() << endl;print_list(lst2);// sort举例list<int> lst4{23, 1, 56, 78, 44, 35, 99, 76};cout << "---------- before sort, lst4 ---------- " << endl;print_list(lst4);cout << "---------- after sort, lst4 ---------- " << endl;lst4.sort();print_list(lst4);
}
int main()
{test01();system("pause");return 0;
}result:
---------- push_back ---------- 1
push_back
---------- push_front ---------- 2
push_front push_back
---------- pop_back ---------- 1
push_front
---------- pop_front, lst1.size() ---------- 0---------- lst2.insert(++lst2.begin(), 222), lst2.size() ---------- 7
1 222 2 3 4 5 6
---------- lst2.insert(--lst2.end(), 3, 666), lst2.size() ---------- 10
1 222 2 3 4 5 666 666 666 6
---------- lst2.insert(lst2.end(), vec1.begin(), vec1.begin()+3), lst2.size() ---------- 13
1 222 2 3 4 5 666 666 666 6 11 22 33
---------- lst2.erase(++lst2.begin()), lst2.size() ---------- 12
1 2 3 4 5 666 666 666 6 11 22 33

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

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

相关文章

覃嘉仪,艺人经纪人、经纪人、影视经纪人。2002.7.9出生于四川省遂宁市射洪县

覃嘉仪&#xff0c;艺人经纪人、经纪人、影视经纪人。2002.7.9出生于四川省遂宁市射洪县 2020年开始从事宣传工作&#xff0c;2023成为“WP经纪工作室”艺人经纪&#xff0c;现担任孙亦欣、魏逸熙等艺人的经纪人。 2024年涉足于影视行业&#xff0c;并加入嘉林娱乐。2024年在由…

慢慢写材料

有一次&#xff0c;我要公司帮我提供一个材料。当时&#xff0c;我比较着急&#xff0c;于是非常简要、快速的写了一封邮件&#xff0c;发给公司负责人。 结果&#xff0c;两三天后&#xff0c;也没有收到公司的回复。 于是&#xff0c;我又耐心的写了一封新的邮件。说明&#…

华为云CCE集群创建loadBalancer

目录 一、目的 二、创建应用 三、创建服务 loadBalancer 四、域名解析 五、验证 一、目的 1、为CCE容器应用创建loadBalancer服务&#xff0c;并且绑定https协议的域名 2、公网访问域名: https://test.******.com 3、CCE创建用于公网域名访问的loadBalancer&#xff0c;不…

网站安全问题整改

网站安全、政务云、第三方安全检测机构等评测出来的网站web安全问题整改&#xff0c;如果你也正需要做这方面&#xff0c;请联系我吧

快速排序(动图详解)(C语言数据结构)

快速排序&#xff1a; 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&#xff1a; 任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&#xff0c…

个人怎么注册商标需要什么条件!

经常会遇到有人问普推知产老杨&#xff0c;个人怎么注册商标需要什么条件&#xff0c;首先会要有个体户执照&#xff0c;没有得先申请一个体工商户的执照才可以申请注册商标&#xff0c;再加身份证正反签字就可以&#xff0c;申请商标类别的类别与个体工商户经营范围无关&#…

APP 数据抓取 - Charles 抓包工具的使用(Charles 端口配置、CA 证书配置、Charles Android 模拟器配置)

前言说明 此文章是我在学习 Charles APP 抓包时编写&#xff0c;内容都是亲测有效&#xff0c;文章内容也有参考其他人&#xff0c;参考文章如下&#xff1a; Android 手机使用 charles 抓 https 请求&#xff08;保姆级教程&#xff09;网易 mumu 模拟器安装下载 charles 的…

redroid搭建云手机学习笔记(一)

参考链接 通过Redroid搭建自己的云手机 docker安装 docker官网目前打不开了&#xff0c;通过官网安装的方式无法实现&#xff0c;这里需要借助镜像网站来实现docker的安装 参考链接&#xff1a;https://developer.aliyun.com/mirror/docker-ce # step 1: 安装必要的一些系统…

ADB 获取屏幕坐标,并模拟滑动和点击屏幕

本文声明:本文是参考https://blog.csdn.net/beyond702/article/details/69258932编制。同时,补充了在windows系统模式下,详细的获取屏幕坐标的步骤。 1.判断设备与windows电脑USB连接是否正常 在CMD窗口输入命令:ADB devices,按ENTER键,输出如下结果,则表示连接正常。 …

【非常简单】 猿人学web第一届 第17题 天杀的 Http2.0

题目标题已经很明显了&#xff0c;Http2.0 数据接口 对应的请求协议也为 http2.0 python 代码 import httpx # pip install httpxheaders {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.…

LangChain学习资料

本文提供了一个LangChain框架的综合资源库&#xff0c;包括低代码工具、服务、代理、模板等&#xff0c;还列举了知识管理和聊天机器人等开源项目&#xff0c;以及学习笔记、视频教程等学习资料&#xff0c;旨在帮助开发者更好地利用和学习LangChain。 摘要由CSDN通过智能技术…

【深海王国】小学生都能玩的单片机!番外2:Arduino控制其他元器件(2)

Hi٩(๑ ^ o ^ ๑)۶, 各位深海王国的同志们&#xff0c;早上下午晚上凌晨好呀~辛勤工作的你今天也辛苦啦 (o゜▽゜)o☆ 今天大都督为大家带来单片机的新番外系列——小学生都能玩的单片机&#xff01;番外2&#xff1a;Arduino控制其他元器件&#xff0c;带你学习如何使用Ard…

【ragflow】安装2:源码安装依赖

中文文档【ragflow】安装1: docker:失败官方说的成功 docker 安装的启动失败 重新来一遍,不会重新拉取: root@k8s-master-pfsrv:/home/zhangbin/perfwork/rag# cd ragflow/ root@k8s-master-pfsrv:/home/

单片机-串口通信(二)

目录 一、串口概念 1.相关概念&#xff1a; 按数据传输方式分类&#xff1a; 按时钟分类 二、STM32F103ZET6中串口 USART特性&#xff1a; NRZ数据格式&#xff1a; 三、配置串口通信 查看硬件原理图 软件配置流程 USART相关的寄存器 新建my_usart1.c和my_usart1.h …

游戏开发者必看:Perforce龙智即将携手亮相2024 Unreal Fest上海站,打造游戏开发版本控制新生态

2024年9月5- 6日&#xff08;周四-周五&#xff09;&#xff0c;Unreal Fest Shanghai 2024将在上海宝华万豪酒店隆重举行&#xff01;作为游戏行业备受瞩目的盛会之一&#xff0c;Unreal Fest每年都会吸引来自世界各地的技术专家和行业领导者齐聚一堂&#xff0c;分享最新的技…

LabVIEW中升采样和降采样

升采样 (Upsampling) 和 降采样 (Downsampling) 是信号处理中的两种常见操作&#xff0c;用于改变信号的采样率。它们在数字信号处理&#xff08;DSP&#xff09;和许多工程应用中非常重要&#xff0c;尤其是在处理不同采样率的数据流时。 升采样 (Upsampling) 升采样是增加信…

W.A.L.T: Photorealistic Video Generation with Diffusion Models

Paper name W.A.L.T: Photorealistic Video Generation with Diffusion Models Paper Reading Note Paper URL: https://arxiv.org/pdf/2312.06662 Project URL: https://walt-video-diffusion.github.io/ TL;DR 2023 斯坦福大学和 google 联合出品的视频生成工作&#x…

ssm面向企事业单位的项目申报小程序论文源码调试讲解

2 系统实现的技术支持 2.1微信开发者工具 在传统web浏览器中&#xff0c;在加载htm15页面时先加载视图层的html和css&#xff0c;后加载逻辑层的java script&#xff0c;然后返回数据并在浏览器中展示页面。而微信开发者工具的系统层是基于Native System的&#xff0c;视图层和…

Excel 导入和导出--前后端整合

文章目录 Excel基础Easy Excel导出会员数据导入会员数据 前端代码:代码解析总结组件简介详细解释总结 用来操作excel文件的。银行网银系统导出交易明细数据、各种业务系统导出excel报表数据、批量导入业务数据。 Excel基础 **工作簿 workbook**就是一个文件工作表 sheet属于…

Linux中如何查看一个进程?如何杀死一个进程?如何查看某个端口有没有被占用?

在Linux中 如何查看一个进程&#xff1f; 使用 ps 命令 ps aux这会显示所有正在运行的进程&#xff0c;可以使用 grep 来过滤特定的进程 ps aux | grep process_name使用 top 命令 top这个命令会实时的显示系统重正在运行的进程 如何杀死一个进程&#xff1f; 使用 kill …