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.mzph.cn/web/52030.shtml

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

相关文章

vant 动态查询下拉菜单(可用)

动态查询item项 <van-form submit"onSubmit" ref"formRef"><Title title"企业信息" title-line title-size"19" class"ml-[18px] mb-[18px]"></Title><van-cell-group inset class"py-[18px]&quo…

Python实战项目:天气数据爬取+数据可视化(完整代码)_python爬虫实战

一、选题的背景 随着人们对天气的关注逐渐增加&#xff0c;天气预报数据的获取与可视化成为了当今的热门话题&#xff0c;天气预报我们每天都会关注&#xff0c;天气情况会影响到我们日常的增减衣物、出行安排等。每天的气温、相对湿度、降水量以及风向风速是关注的焦点。通过…

Linux——网络(5)

一、sqlite3性能测试 1. 程序效率测试 时间相关接口&#xff1a; int gettimeofday(struct timeval*tv, struct timezone *tz); 功能&#xff1a;得到从1970年1月1日0时0分0秒到现在的秒数 精度到微妙 参数&#xff1a; tv&#xff1a;…

什么是视频缓存服务器,它有哪些作用?

视频缓存服务器通常拥有大容量的存储空间和高速的读写能力&#xff0c;它通过缓存(即临时存储)用户经常访问的视频内容&#xff0c;来优化内容的分发过程。这种服务器通常部署在网络中的关键位置&#xff0c;如靠近用户接入点的位置&#xff0c;以降低用户访问视频内容时的网络…

维信小程序禁止截屏/录屏

一、维信小程序禁止截屏/录屏 //录屏截屏,禁用wx.setVisualEffectOnCapture({visualEffect:hidden});wx.setVisualEffectOnCapture(Object object) 测试安卓手机&#xff1a; 用户截屏&#xff0c;被禁用 用户录屏&#xff0c;录制的是空白内容/黑色内容的视频。 二、微信小…

鸿蒙系统为什么能安装安卓的APP

鸿蒙系统能够安装安卓的APP&#xff0c;主要得益于其设计理念和技术实现上的几个关键点&#xff1a; 一、设计理念 鸿蒙系统的设计初衷并非完全取代安卓系统&#xff0c;而是与其共存&#xff0c;并建立一个更加广泛的软件生态圈。这一理念体现在鸿蒙系统对安卓应用的兼容性上…

浙大数据结构:01-复杂度2 Maximum Subsequence Sum

数据结构MOOC PTA习题 01-复杂度2 Maximum Subsequence Sum #include <iostream> using namespace std; const int M 100005; int a[M]; int main() {int k;cin >> k;int f 1;for (int i 0; i < k; i){cin >> a[i];if (a[i] > 0)//如果出现大于0则…

【HuggingFace Transformers】OpenAIGPTModel源码解析

OpenAIGPTModel源码解析 1. GPT 介绍2. OpenAIGPTModel类 源码解析 说到ChatGPT&#xff0c;大家可能都使用过吧。2022年&#xff0c;ChatGPT的推出引发了广泛的关注和讨论。这款对话生成模型不仅具备了强大的语言理解和生成能力&#xff0c;还能进行非常自然的对话&#xff0c…

1.初识ChatGPT:AI聊天机器人的革命(1/10)

引言 在当今的数字化世界中&#xff0c;人工智能&#xff08;AI&#xff09;正以其独特的方式重塑我们的生活和工作。其中&#xff0c;AI聊天机器人作为人机交互的前沿技术&#xff0c;已经成为企业与客户沟通、提供个性化服务的重要工具。这些机器人通过模拟人类的对话方式&a…

二、MMRotate旋转框目标检测训练DOTA数据集(模型推理与部署,保存推理结果为xml文件并构建镜像)

在上一篇文章中介绍了MMRotate的概述、安装和训练Dota数据集全流程,由于文章篇幅限制还剩下一部分模型的推理和部署环节没有写,为避免后续对这部分工作的遗忘,决定还是补充上这部分的笔记,仅作记录,如有不足之处还请指出! 一、模型推理测试 1.1单张图片推理测试 可以首…

DataSet和DataTable的关系

C#中的DataTable 在C#中&#xff0c;DataTable 是 System.Data 命名空间下的一个类&#xff0c;它是 DataSet 的一个组件&#xff0c;用于存储表格形式的数据。DataTable 可以独立于数据库使用&#xff0c;也可以与数据库表相关联&#xff0c;用于数据的读取、更新、插入和删除…

LeetCode 热题100-17 缺失的第一个正数

缺失的第一个正数 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围 [1,…

OpenCV绘图函数(13)绘制多边形函数函数polylines()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 画几条多边形曲线 函数原型 void cv::polylines (InputOutputArray img,InputArrayOfArrays pts,bool isClosed,const Scalar & color…

【高等代数笔记】(18)N阶行列式

2. N阶行列式 2.12 行列式按k行&#xff08;列&#xff09;展开 【拉普拉斯定理】 n n n阶矩阵 A ( a i j ) \boldsymbol{A}(a_{ij}) A(aij​)&#xff0c;取定第 i 1 , i 2 , . . . , i k i_{1},i_{2},...,i_{k} i1​,i2​,...,ik​行&#xff08;其中 i 1 < i 2 < .…

将x减到零的最小操作数问题

欢迎跳转我的主页&#xff1a;羑悻的小杀马特-CSDN博客 目录 一题目简述&#xff1a; 二题目思路&#xff1a; 三解答代码&#xff1a; 一题目简述&#xff1a; leetcode题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 二题目思路&#xff1a; 首先这道题…

STM32(F103ZET6)第十九课:FreeRtos的移植和使用

目录 需求一、FreeRtos简介二、移植FreeRtos1.复制代码2.内存空间分配和内核相关接口3.FreeRtosConfig4.添加到工程中三、任务块操作1.任务四种状态2.创建任务过程 需求 1.将FreeRtos&#xff08;嵌入式实时操作系统&#xff09;移植到STM32中。 2.在该系统中实现任务的创建、…

git 更改分支名称

1. 本地分支重命名&#xff08;还未推送到远程&#xff09; 1、修改当前分支名称 git branch -m 新分支名称2、修改其他分支名称 git branch -m 旧分支名称 新分支名称2. 远程分支重命名&#xff08;已推送远程&#xff09; 1&#xff09;重新命名远程分支对应的本地分支 …

86、pod部署策略

一、集群的调度 集群的调度&#xff1a; 怎么把pod部署到节点的方法。 1.1、调度的过程&#xff1a; scheduler是集群的调度器&#xff0c;主要任务就是把pod部署到节点上。 1.2、自动调度&#xff1a; 1、公平&#xff0c;保证每个可用的节点都可以部署pod 2、资源的高…

【生日视频制作】黑板写文字美女跳舞2版AE模板修改文字软件生成器教程特效素材【AE模板】

生日视频制作教程黑板写文字美女跳舞2版AE模板修改文字特效广软件告生成神器素材祝福玩法AE模板替换工程 怎么如何做的【生日视频制作】黑板写文字美女跳舞2版AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件 下载AE模板 把AE模板导…

有向无环图的关联矩阵及其矩阵乘积的含义

有向无环图的关联矩阵及其矩阵乘积的含义 引言关联矩阵的定义矩阵乘积 B B T BB^T BBT的含义伪代码示例C代码示例结论引言 在计算机科学和数学中,有向无环图(Directed Acyclic Graph, DAG)是一种常见的数据结构,广泛应用于各种算法中,如拓扑排序、动态规划等。在有向无环…