C++系列-STL容器之list

news2024/11/15 18:06:49

STL容器之list

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

list容器的基本结构

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

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

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大小及空否

接口函数说明
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++)
	{
		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;		// front() 头元素
	print_list<int>(lst1);
	cout << "lst1.front(): " << lst1.front() << endl;		// front() 头元素
	cout << "lst1.back(): " << lst1.back() << endl;			// back() 尾元素

	cout << "* lst1.begin(): " << *lst1.begin() << endl;	// 迭代器指向第一个元素
	cout << "* (--lst1.end()): " << *(--lst1.end()) << endl;// 迭代器指向末尾元素的下一个
	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, num, const T &val)
	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

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;					// assign{初始化列表}
	lst5.assign(vct1.begin(), vct1.begin()+2);
	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

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

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

相关文章

Java笔试面试题AI答之面向对象(8)

文章目录 43. 解释Java接口隔离原则和单一原则如何理解 &#xff1f;单一职责原则&#xff08;Single Responsibility Principle, SRP&#xff09;接口隔离原则&#xff08;Interface Segregation Principle, ISP&#xff09; 44. Java 有没有 goto? 如果有&#xff0c;一般用…

004.Python爬虫系列_web请求全过程剖析(重点)

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

2024年8月31日历史上的今天大事件早读

1449年8月31日 明朝“土木之变” 1907年8月31日 英、法、俄三国协约形成 1914年8月31日 “骆派”京韵大鼓的创建者骆玉笙诞生 1916年8月31日 蔡锷东渡日本养病 1935年8月31日 美国通过《中立法案》 1937年8月31日 日本华北方面军成立 1941年8月31日 晋察冀边区完成民主大…

2024最新最全:国内外人工智能AI工具网站大全!

国内外人工智能AI工具网站大全&#xff08;一键收藏&#xff0c;应有尽有&#xff09; 摘要一、AI写作工具二、AI图像工具 2.1、常用AI图像工具2.2、AI图片插画生成2.3、AI图片背景移除2.4、AI图片无损调整2.5、AI图片优化修复2.6、AI图片物体抹除 三、AI音频工具四、AI视频工…

南京观海微电子----CMOS门电路(OD门、传输门、双向模拟开关、三态门)

【 1. MOS管】 MOS管&#xff1a;绝缘栅型场效应管。 【 2. CMOS电路】 当NMOS管和PMOS管成对出现在电路中&#xff0c;且二者在工作中互补&#xff0c;称为CMOS管(Complementary Metal-Oxide-Semiconductor)。 电路结构 拉电流 如下图所示&#xff0c;输入低电平&#xff…

王者荣耀 设置游戏头像 不用微信头像

我们在微信 我 选择 设置 在里面找到 个人信息与权限 如果找不到看看有木有一个叫隐私的选项 点击 进入之后 选择授权管理 找到王者荣耀 然后点击右侧的小箭头进入 点击下面的 解除授权 确认一下 解除授权 然后重新打开王者 选择微信登录 我们这里 选择新建昵称头像 选…

线性代数之线性方程组

目录 线性方程组 1. 解的个数 齐次线性方程组&#xff1a; 非齐次线性方程组&#xff1a; 2. 齐次线性方程组的解 3. 非齐次线性方程组的解 4. 使用 Python 和 NumPy 求解线性方程组 示例代码 齐次线性方程组 非齐次线性方程组 示例结果 齐次线性方程组 非齐次线性…

Unity获取SceneView尺寸

获取SceneView尺寸 var sceneView SceneView.lastActiveSceneView; var size new Vector2(sceneView.position.width,sceneView.position.height);

Elasticsearch学习(1)-mac系统安装elasticsearch基础

Elasticsearch基础 1. 传统数据库与elasticsarch2. 下载Elasticsearch7. 经过上述所有操作&#xff0c;就可以得到一个具体的连接可视化页面3. 安装kibana4. 其余知识点 elasticsearch是什么&#xff1f; Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能…

sql-labs靶场(41-50)

四十一 1.查看数据库名 ?id-1 union select 1,2,database()-- 2.查看表名 ?id-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase()-- 3.查看user表列名 ?id-1 union select 1,group_concat(column_name),3 from…

SpringMVC处理流程介绍

SpringMVC请求处理流程 发起请求到前端控制器(DispatcherServlet)前端控制器请求HandlerMapping查找Handler(可以根据xml配置,注解进行查找) 对应Spring源码 //在类DispatcherServlet里面 protected void doDispatch(HttpServletRequest request, HttpServletResponse respon…

Leetcode102二叉树的层序遍历(java实现)

今天分享的题目是lee102题&#xff0c;题目的描述如下&#xff1a; 可能做到这道题的小伙伴写过其他关于二叉树的题目&#xff0c;但是一般是使用递归的方式做一个深度遍历&#xff0c;而层序遍历我们该如何做呢&#xff1f; 解题思路&#xff1a;使用一个队列来记录本层节点&a…

浅谈新能源汽车充电桩安装以及防范

摘要&#xff1a;随着国家对绿色环保的倡导&#xff0c;新能源电动汽车应运而生&#xff0c;它们采用清洁能源替代传统能源&#xff0c;有效避免了对自然环境的污染&#xff0c;并减少了资源消耗&#xff0c;实现了资源的高效利用。新能源电动汽车的普及降低了使用成本&#xf…

Rust Linux开发人员自比道路建设者和寻路者的区别

红帽公司&#xff08;Red Hat&#xff09;的长期直接渲染管理器&#xff08;Direct Rendering Manager&#xff0c;DRM&#xff09;子系统维护者大卫-艾尔里&#xff08;David Airlie&#xff09;撰写了一篇有趣的博文&#xff0c;将开发人员的类型与筑路工人、寻路者与酒店进行…

800G OSFP光模块发展概述

在快速发展的高速网络领域&#xff0c;800G OSFP光模块的演变象征着创新与进步。自诞生以来&#xff0c;800G OSFP光模块凭借哪些独特优势脱颖而出&#xff1f;本文将重点介绍800G OSFP光模块的发展路径。 800G OSFP光模块发展路径 路径一&#xff1a;EML 路由 800G DR8 OSF…

Python进阶07-高级语法

零、文章目录 Python进阶07-高级语法 1、with语句 &#xff08;1&#xff09;文件操作 文件使用完后必须关闭&#xff0c;因为文件对象会占用操作系统的资源&#xff0c;并且操作系统同一时间能打开的文件数量也是有限的 # 第一步&#xff1a;打开文件 f open(python.txt…

另一种关于类的小例

前言 我们还是以一段关于构造函数的代码作为开端&#xff0c;我们以之前银行家的小项目为背景 class Account {constructor(owner, currency, pin) {this.owner owner;this.currency currency;this.pin pin;} }const ITshare new Account(ITshare, EUR, 21211); console.…

堆垛机及AGV能力计算

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载。 这份文件是关于堆垛机和AGV&#xff08;…

第六课,模运算进阶,计算机存储单位

一&#xff0c;模运算的进阶知识 先复习一下已知的模运算知识&#xff1a; ①符号是%&#xff0c;但作为模运算符号时应念作“模”而非“百分之”或“百分号” ②参与模运算的数必须是两个整数&#xff0c;其作用是计算余数 然后新学几个模运算知识&#xff1a; ③当被除数是…

IPv4和子网掩码

目录 IP地址&#xff1a; IP概念&#xff1a; 网络号与主机号&#xff1a; 网关与跨网通信&#xff1a; IP地址的分类&#xff1a; 子网掩码&#xff1a; 如何确定两个IP地址是否在同一网段; 练习&#xff1a; 补充&#xff1a; IP地址&#xff1a; IP概念&#xff1…