STL常用容器—list容器(链表)

news2024/9/24 13:19:58

STL常用容器—list容器(链表)

  • 一、list容器基本概念
  • 二、list容器基本操作与常用方法
    • 1. list构造函数
    • 2. ☆list 插入和删除
    • 3. list 获取头尾数据
    • 4. list 大小操作
    • 5. list赋值和交换
    • 6. list 反转和排序
  • 三、排序案例

参考博文1: <C++> list容器本质|常用接口|自定义排序规则
参考博文2:STL常用容器—— list 容器的使用

  本文主要整理总结C++ STL中list(链表)常用容器的常用方法的操作,关于链表的底层设计与C语言实现请参考博文:【数据结构与算法】——单链表的原理及C语言实现

一、list容器基本概念

  list 容器 的本质是一个双向循环链表,用于存储的每个结点包含数据域指针域

示意图:

名词解释:

  • beginend 都是迭代器,可以看成指针来操作
    begin 对应的是容器首个元素,而end 对应容器最后一个元素的下一个位置
  • prevnext 代表前驱指针和后继指针,并不是 list 容器的接口,指针域用来存储下一个结点的地址
  • frontback 分别是第一个和最后一个结点的数据域
  • push_backpush_frontpop_backpop_front 代表尾插、头插、尾删、头删

通过前驱后继指针可以将每个结点连接起来,头结点的前驱与尾结点后继指针都指向null
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

list的优点:

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 可以对任意位置进行快速插入或删除元素,修改指针即可,不需要移动大量元素

list的缺点:

  • 链表灵活,但是空间(指针域)和 时间(遍历)额外耗费较大

STL中List和vector是两个最常被使用的容器,各有优缺点

二、list容器基本操作与常用方法

1. list构造函数

函数原型功能
list<T> lst;采用模板类实现,对象的默认构造形式
list<T> lst = {x1,x2...};构造并出初始化
list(n,elem);n个elem
list(const list &lst);拷贝构造函数
list(beg,end);构造函数将[beg, end)区间中的元素拷贝给本身

示例:

list<int> list1;
list1.push_back(10);
list1.push_back(20);
list1.push_back(30);

list<int> list2={2,4,6,8};//构造并初始化
list<int> list3(5,100);		//5个100
list<int> list4(list1);		//拷贝list1

//list2的部分区间
list<int> list5(++list2.begin(), --list2.end());		

cout << "list1: ";	showList(list1);
cout << "list2: ";	showList(list2);
cout << "list3: ";	showList(list3);
cout << "list4: ";	showList(list4);
cout << "list5: ";	showList(list5);

其中showList:

void showList(list<int> &list)
{
	for(int item:list)
		cout << item  << " ";
	cout << endl;
}

2. ☆list 插入和删除

方法原型功能
-----------常用-----------
push_back(elem);在容器尾部插入一个元素
push_front(elem);在容器开头插入一个元素
pop_back();删除容器中最后一个元素
pop_front();删除容器中第一个元素
clear();清空容器所有数据
-----------不常用-----------
insert(pos,elem);在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);在pos位置插入[beg,end)区间的数据,无返回值
erase(beg,end);删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos);删除pos位置的数据,返回下一个数据的位置
remove(elem);删除容器中所有与elem值匹配的元素。

示例:

void test()
{
	
	list<int> list1;
	//尾插
	list1.push_back(2);	
	list1.push_back(4);
	//头插
	list1.push_front(10);
	list1.push_front(30);
	cout << "list1 push back + front: ";
	showList(list1);			//30 10 2 4

	//尾删
	list1.pop_back();
	cout << "pop back: ";	
	showList(list1);			//30 10 2

	//头删
	list1.pop_front();
	cout << "pop front: ";	
	showList(list1);			//10 2

	//头+1插
	list1.insert(++list1.begin(), 666);
	cout << "front insert: ";	
	showList(list1);			//10 666 2

	//头+1删
	list1.erase(++list1.begin());
	cout << "front+1 erase: ";	
	showList(list1);			//10  2
}

3. list 获取头尾数据

  list 容器不支持随机访问,不提供下标操作符 [] 和 at() 成员函数,也没有提供 data() 成员函数。
  只能使用 front() 和 back() 成员函数,或者使用 list 容器迭代器访问或修改元素的值。

使用 front() 和 back() 成员函数

方法原型功能
front();返回第一个元素
back();返回最后一个元素
int main()
{
	list<int> list1 = {2,4,6,8,10};
	
	//获取元素引用
	int& first = list1.front();
	int& last  = list1.back();
	cout << first << " " << last << endl;
	
	//修改元素
	first = 100;
	last  = 200;
	cout << list1.front() << " " << list1.back() << endl;
	
	return 0;
}

注意:

  • list容器中不可以通过[]或者at方式访问数据
  • 返回第一个元素 — front
  • 返回最后一个元素 — back

使用 list 容器迭代器

int main()
{
	list<int> list1 = {2,4,6,8,10};
	auto it = list1.begin();	//迭代器指向头
	while(it != list1.end())	//迭代遍历
	{
		cout << *it << " ";
		it++;					//迭代器自增
	}
	return 0;
}

注意: list容器的迭代器类型为双向迭代器,而不是和之前的array、vector容器一样是随机访问迭代器。

双向迭代器特性:假如it1,it2都是双向迭代器,那么:

支持:++it1、 it1++、 it1- -、 it1++、 *it1、 it1 == it2 以及 it1 != it2
不支持:it1[i]、it1-=i、 it1+=i、 it1+i 、it1-i、it1 < it2、it1 > it2、 it1 <= it2、 it1 >= it2

4. list 大小操作

方法原型功能
size(); 返回容器中元素的个数
empty(); 判断容器是否为空
resize(num);重新指定容器的长度为num,若容器变长,则以默认值0填充;若变短,则删除末尾多余元素
resize(num, elem); 重新指定容器的长度为num,若容器变长,则以 elem 填充;若变短,则删除末尾多余元素

示例程序:

void test()
{
	list<int> list1 = {10,20,30};
	list<int> list2 = {2,4,6,8,10};
	
	if(!list1.empty())
	{
		cout << "size: " << list1.size() << endl;
		list1.resize(5);	//重置大小为5个,以默认值填充
		cout << "resize: " << list1.size() << endl;
		showList(list1);
	}
	else
		cout << "容器为空" << endl;
}

5. list赋值和交换

方法原型功能
assign(beg, end);将[beg, end)区间中的数据拷贝赋值给本身
assign(n, elem);将n个elem拷贝赋值给本身
list& operator=(const list &lst);已重载 = 操作符
swap(lst);将list与本身的元素互换

示例:

list<int> list1 = {10,20,30};
list<int> list2 = {2,4,6,8,10};

list1 = list2;			
showList(list1);	//2,4,6,8,10

list1.assign(5,100);	
showList(list1);	//5个100

list1.assign(++list2.begin(),--list2.end());	
showList(list1);	//4,6,8

list1.swap(list2);
showList(list1);	//2,4,6,8,10
showList(list2);	//4,6,8

6. list 反转和排序

方法原型功能
reverse();反转链表
sort();链表排序

示例:

//用于降序排序
bool myCompare(int v1, int v2)
{
	//降序:让第一个数 > 第二个数
	return v1 > v2;
}

void test03()
{
	list<int> list1 = {6,4,2,10,3};
	cout << "src data: ";	showList(list1);
	
	//降序排序
	list1.sort(myCompare);
	cout << "sort: "; 		showList(list1);
	
	//反转
	list1.reverse();
	cout << "reverse: ";	showList(list1);
}

sortlist 容器内部的排序方法,默认为升序排列,需要通过自己编写函数(仿函数)来决定排序的规则。

三、排序案例

案例描述: 将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高
排序规则: 按照年龄进行升序,如果年龄相同按照身高进行降序

示例程序:

/******************自定义Person类****************/
class Person {
public:
	Person(string name, int age , int height)
	{
		this->name = name;
		this->age = age;
		this->height = height;
	}

public:
	string name;  //姓名
	int age;      //年龄
	int height;   //身高
};
/*****************定义仿排序顺序 仿函数**************/
bool PersonCompare(Person &p1, Person &p2)
{
	if(p1.age == p2.age)	//年龄相同 按身高降序
	{
		if(p1.height > p2.height)
			return true;
		else
			return false;
	}
	else	//按年龄升序
	{
		if(p1.age < p2.age)
			return true;
		else
			return false;
	}		
}
/****************遍历容器函数**************/
void showPersonList(list<Person> &list)
{
	auto it = list.begin();
	for( ; it != list.end(); it++)
	{
		cout << "name: " << it->name << "\tage: " << it->age;
		cout << "\t\theight: " << it->height << endl;
	}
}
/*****************主程序 测试程序*************/
void test04()
{
	Person p1("张三", 22, 170);
	Person p2("李四", 21, 173);
	Person p3("王五", 20, 168);
	Person p4("陈六", 25, 177);
	Person p5("赵七", 22, 180);
	list<Person> list1 = {p1,p2,p3,p4,p5};

	//排序前
	cout << "before sort: " << endl; 
	showPersonList(list1);
	
	//自定义排序
	list1.sort(PersonCompare);
	//显示排序后结果
	cout << "after sort: " << endl; 
	showPersonList(list1);
}

程序输出:

总结:

  • 对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
  • 高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂

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

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

相关文章

Cambalache in Ubuntu

文章目录 前言apt install flatpak这很ok后记 前言 gtkmm4相比gtkmm3有很多改革, 代码也干净了许多, 但在windows上开发 有ui设计器那自然方便很多, 但glade又不支持gtkmm4, windows上装Cambalache很是困难. 各种问题都找不到答案.于是 我用VMware虚拟机Ubuntu20.xx安装Cambal…

深度学习:数据驱动的人工智能革命

文章目录 每日一句正能量前言什么是深度学习推动AI发展不同阶段的“三大驱动 ”1、技术驱动&#xff1a;算法和计算力是主要驱动力2、计算力的三驾马车&#xff1a;芯片、超级计算机、云计算3、数据驱动&#xff1a;描绘个性化画像&#xff1b; 后记 每日一句正能量 一般青年的…

日志追踪-Tracing

1. 前言 分布式链路跟踪中有两个重要的概念&#xff1a;跟踪&#xff08;trace&#xff09;和 跨度&#xff08; span)。trace 是请求在分布式系统中的整个链路视图&#xff0c;span 则代表整个链路中不同服务内部的视图&#xff0c;span 组合在一起就是整个 trace 的视图在整个…

BUUCTF-Real-[struts2]s2-013

struts2的标签中 <s:a> 和 <s:url> 都有一个 includeParams 属性&#xff0c;可以设置成如下值none - URL中不包含任何参数&#xff08;默认&#xff09; get - 仅包含URL中的GET参数 all - 在URL中包含GET和POST参数 当includeParamsall的时候&#xff0c;会将本次…

学术研究新突破:发现新型相变存储器

斯坦福大学的研究人员开发出了一种新型相变存储器&#xff0c;该存储器有望帮助计算机更快、更高效地处理大量数据。在最近发表于《自然通讯》的一篇论文中&#xff0c;研究人员详细介绍了这项技术&#xff0c;表明一种新材料可能会使基于电阻高低状态切换以创建计算机数据“0”…

2024美赛数学建模D题思路+代码

文章目录 1 赛题思路2 美赛比赛日期和时间3 赛题类型4 美赛常见数模问题5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 美赛比赛日期和时间 比赛开始时间&#xff1a;北京时间2024年2月2日&#xff08;周五&#xff…

Blender教程(基础)-面的尖分、三角化与融并-09

一.面的尖分 1.准备 新建如下图所示物体、切换到编辑模式下 2.右键尖分正方形面 在选择中的面上右键选择尖分面 效果如下所示 3.右键尖分圆形面 效果如下 可以自行调节参数 二.面的三角化 1、正方形 2、圆形 三.融并 1、尖分圆形面 2、尖分圆形面-融并 发现…

Unity Meta Quest MR 开发(三):Scene API 配置+实现虚拟与现实之间的碰撞

文章目录 &#x1f4d5;教程说明&#x1f4d5; Scene 配置⭐开启场景理解功能和应用访问空间数据的权限⭐OVRSceneManager⭐制作 Plane Prefab 和 Volume Prefab⭐运行场景⭐添加透视材质 &#x1f4d5;虚拟与现实物体的碰撞&#xff08;弹球 Demo&#xff09;&#x1f4d5;Mes…

两数之和 - 暴力枚举+哈希表

两数之和原题地址 方法一&#xff1a;暴力枚举 首先&#xff0c;我们需要枚举数组中所有可能的下标对组合&#xff0c;对于n个数的数组&#xff0c;从中选2个下标&#xff0c;有种可能。做法很简单&#xff0c;遍历数组中的所有元素&#xff0c;对于每一个元素&#xff0c;遍…

yo!这里是c++IO流相关介绍

目录 前言 C语言的输入输出 CIO流基本介绍 流的概念 IO流类库 iostream fstream stringstream 后记 前言 学过C语言的输入输出相关知识点的童鞋应该多多少少会觉得有些许麻烦&#xff0c;反正我就是这么觉得的&#xff0c;scanf、printf等函数不仅数量众多&#xff0c…

RNN实战具体跑的代码

一、首先先上代码&#xff1a;这个是接pytorch API的调用代码 import torch import torch.nn as nn bs, T 2,3#批次大小&#xff0c;输入序列长度 input_size,hidden_size2,3#输入特征大小&#xff0c;隐含层特征大小 input torch.randn(bs,T, input_size) h_prev torch.ze…

css新手教程

css新手教程 课程&#xff1a;14、盒子模型及边框使用_哔哩哔哩_bilibili 一.什么是CSS 1.什么是CSS Cascading Style Sheet 层叠样式表。 CSS&#xff1a;表现&#xff08;美化网页&#xff09; 字体&#xff0c;颜色&#xff0c;边距&#xff0c;高度&#xff0c;宽度&am…

用户体验优化:HubSpot的秘密武器

在当今数字化市场中&#xff0c;提升用户体验已经成为企业成功的关键因素之一。HubSpot&#xff0c;作为一款领先的营销自动化工具&#xff0c;不仅在推动销售业绩上表现出色&#xff0c;同时通过其独特的策略也致力于提升用户体验。运营坛将深入探讨HubSpot是如何通过个性化推…

Leetcode92:反转链表II(区间反转链表)

一、题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a…

Redisson看门狗机制

一、背景 网上redis分布式锁的工具方法&#xff0c;大都满足互斥、防止死锁的特性&#xff0c;有些工具方法会满足可重入特性。如果只满足上述3种特性会有哪些隐患呢&#xff1f;redis分布式锁无法自动续期&#xff0c;比如&#xff0c;一个锁设置了1分钟超时释放&#xff0c;…

Servlet+Ajax实现对数据的列表展示(极简入门)

目录 1.准备工作 1.数据库源&#xff08;这里以Mysql为例&#xff09; 2.映射实体类 3.模拟三层架构&#xff08;Dao、Service、Controller&#xff09; Dao接口 Dao实现 Service实现&#xff08;这里省略Service接口&#xff09; Controller层&#xff08;或叫Servlet层…

Vulnhub billu b0x

0x01 环境搭建 1. 从官方下载靶机环境&#xff0c;解压到本地&#xff0c;双击OVF文件直接导入到vmware虚拟机里面。2. 将虚拟机的网络适配器调成NAT模式&#xff0c;然后开机即可进行操作了。 0x02 主机发现 nmap -sn 192.168.2.0/24 成功获取靶机IP为192.168.2.129。 0x0…

网络时间协议NTP工作模式

单播服务器/客户端模式 单播服务器/客户端模式运行在同步子网中层数较高层上。这种模式下,需要预先知道服务器的IP地址。 客户端:运行在客户端模式的主机(简称客户端)定期向服务器端发送报文,报文中的Mode字段设置为3(客户端模式)。当客户端接收到应答报文时,客户端会…

指针2 1月31日学习笔记

一、strncpy、strncmp、strncat函数 strncpy函数用于将一个字符串的一部分拷贝到另一个字符串中。 char* strncpy(char *dest, const char *src, size_t n){size_t i;for (i 0; i < n && src[i] ! \0; i)dest[i] src[i];for ( ; i < n; i)dest[i] \0;return …

2024牛客寒假算法基础集训营1部分题解

// 能力有限&#xff0c;做多少发多少。 A-DFS搜索 题目描述 最近&#xff0c;fried-chicken完全学明白了DFS搜索&#xff08;如上图所示&#xff09;&#xff01;于是学弟向他请教DFS搜索&#xff0c;fried-chicken热心的进行了讲解&#xff1a; 所谓DFS搜索&#xff0c;就…