【C++】 List 基本使用

C++ List 基本使用

基本概念

list 是一个序列容器,它内部维护了一个双向链表结构。与 vectordeque 等基于数组的容器不同,list 在插入和删除元素时不需要移动大量数据,因此在这些操作上具有较高的效率。然而,访问列表中的特定元素通常需要线性时间,因为 list 不提供随机访问迭代器。

list 动态分配内存,每个元素作为一个独立的节点,节点之间通过指针链接,这种结构使得插入和删除操作非常高效。

插入和删除操作

list 提供了多种插入和删除元素的方法,如 push_front, push_back, pop_front, pop_back, insert, erase 等,这些操作通常具有常数时间复杂度 O(1)。

list<int> lst;
lst.push_front(1); // 在列表前端插入元素
lst.push_back(2); // 在列表尾端插入元素
lst.insert(lst.begin(), 0); // 在迭代器指定位置插入元素
lst.erase(lst.begin()); // 删除迭代器指向的元素
lst.pop_front(); // 删除并返回列表前端的元素
lst.pop_back(); // 删除并返回列表尾端的元素
迭代器

list 提供双向迭代器,允许从任意方向遍历列表,而且在插入或删除元素时迭代器保持有效,这是与基于数组的容器如 vector 的主要区别之一。

典型用法

创建和初始化
#include <list>
#include <iostream>

int main() {
    list<int> lst; // 创建一个空列表
    list<int> lst2{1, 2, 3}; // 列表初始化
    list<int> lst3(lst2.begin(), lst2.end()); // 区间初始化
    list<int> lst4 = {4, 5, 6}; // 嵌入式初始化
    return 0;
}
遍历列表
list<int> lst = {1, 2, 3};
for (auto it = lst.begin(); it != lst.end(); ++it) {
    cout << *it << ' ';
}
// 或者使用范围for循环
for (const auto& elem : lst) {
    cout << elem << ' ';
}

常用操作

方法描述
insert()它将新元素插入到迭代器指向的位置之前。
push_back()它在容器的末尾添加了一个新元素。
push_front()它在前面增加了一个新元素。
pop_back()删除最后一个元素。
pop_front()删除第一个元素。
empty()它检查列表是否为空。
size()它查找列表中存在的元素数。
max_size()它找到列表的最大大小。
front()它返回列表的第一个元素。
back()它返回列表的最后一个元素。
swap()当两个列表的类型相同时,它将交换两个列表。
reverse()它反转了列表的元素。
sort()它以递增的顺序对列表中的元素进行排序。
merge()它合并两个排序的列表。
splice()它将新列表插入到调用列表中。
unique()它从列表中删除所有重复的元素。
resize()它更改列表容器的大小。
assign()它将一个新元素分配给列表容器。
emplace()它将在指定位置插入一个新元素。
emplace_back()它将在容器的末尾插入一个新元素。
emplace_front()它将在列表的开头插入一个新元素。

性能考量

虽然 list 在插入和删除方面表现出色,但由于不支持随机访问,因此在需要频繁随机访问元素的场景中,vectordeque 可能是更佳选择。

vector vs list 深入解析与对比

内部结构
  • vector: 基于动态数组实现,优点:支持快速地通过索引随机访问任何元素很好的支持排序、二分查找、堆算法,时间复杂度为O(1)缺点:插入或删除头部元素时效率较低最坏时间复杂度为O(n),且空间不够后增容的代价较大。
  • list: 是一个带头双向循环链表,优点:每个元素都是链表中的一个节点,节点之间通过指针连接。使得插入和删除操作在任何位置都非常高效,时间复杂度为O(1)缺点:不支持随机访问,访问列表中的特定元素需要从头或尾遍历,最坏时间复杂度为O(n)。
迭代器行为
  • vector:当vector容量不足以容纳新的元素时,它会重新分配内存,将所有元素复制到新的内存空间。这个过程会使得之前所有指向vector的迭代器失效。
  • list:迭代器在大多数情况下保持有效。只有当列表中的元素被删除或迭代器被显示重置时,受影响的迭代器才会失效。因为list中的元素都是独立的节点,插入删除操作只需要更新指针指向,不会影响其他节点的地址。
选择场景
  • vector:适用于需要频繁随机访问元素,且主要在容器尾部进行插入和删除操作的场景。
  • list:适用于需要在容器任意位置高效插入和删除元素的场景,特别是在插入和删除操作频率高于随机访问的情况下。

vectorlist是两个相辅相成互补的容器。

汇总
vectorlist
底层结构动态顺序表,一段连续空间带头结点的双向循环链表
随机访问支持随机访问,访问某个元素效率O(1)不支持随机访问,访问某个元素效率O(N)
插入和删除任意位置插入和删除效率低,需要移位,时间复杂度为O(N),插入时可能需要增容。增容:开辟新空间,拷贝元素,释放旧空间,导致效率更低任意位置插入和删除效率高,不需要移位元素,时间复杂度为O(1)
空间利用率底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高底层节点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低
迭代器原生态指针对原生态指针(节点指针)进行封装
迭代器失效在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩展,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响
使用场景需要高效存储,支持随机访问,不关心插入删除率大量插入和删除操作,不关心随机访问
实际应用示例

vector示例:

#include <vector>
#include <iostream>
using namespace std;

int main() {
    std::vector<int> vec = { 1, 2, 3 };
	vec.push_back(4); // 在末尾插入元素
	cout << vec[2] << endl; // 随机访问元素

	auto it = vec.begin() + 2; // 创建指向第3个元素的迭代器
	cout << "头插前:" << *it << endl;

	// 在向量开始插入元素
	vec.insert(vec.begin(), 0);

	// 此时,原先的迭代器it已失效,因为所有的元素都向后移动了一位
	// 下面的代码将触发未定义的行为
	// cout << "头插后:" << *it << std::endl;

	// 正确的做法是重新定位迭代器
	it = vec.insert(vec.begin(), 9); // 利用函数返回值重新指向有效迭代器

	cout << "头插后:" << *it << endl;
    return 0;
}

list示例:

#include <list>
#include <iostream>
using namespace std;

int main() {
    list<int> lst = {1, 2, 3};
    lst.push_front(0); // 在开头插入元素,迭代器有效
    // 让迭代器指向第一个元素
    auto it = lst.begin();
    cout << "插入前:" << *it << endl;
    lst.insert(lst.begin(), 4); // 在任意位置插入元素,迭代器有效
    cout << "插入前:" << *it << endl;
    
    return 0;
}

wallhaven-x63j9v

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无人机航电系统技术详解

一、系统概述 无人机航电系统&#xff08;Avionics System&#xff09;是无人机飞行与任务执行的核心部分&#xff0c;它集成了飞控系统、传感器、导航设备、通信设备等&#xff0c;为无人机提供了必要的飞行控制和任务执行能力。航电系统的设计和性能直接影响到无人机的安全性…

AIGC产品经理学习路径

基础篇&#xff08;课时 2 &#xff09; AIGC 行业视角 AIGC 的行业发展演进&#xff1a;传统模型/深度学习/大模型 AIGC 的产品设计演进&#xff1a;AI Embedded / AI Copilot / AI Agen AIGC 的行业产业全景图 AIGC 的产品应用全景图 AIGC 职业视角 AI 产品经理/ AIGC…

Linux:信号的概念与产生

信号概念 信号是进程之间事件异步通知的一种方式 在Linux命令行中&#xff0c;我们可以通过ctrl c来终止一个前台运行的进程&#xff0c;其实这就是一个发送信号的行为。我们按下ctrl c是在shell进程中&#xff0c;而被终止的进程&#xff0c;是在前台运行的另外一个进程。因…

Android Viewpager2 remove fragmen不生效解决方案

一、介绍 在如今的开发过程只&#xff0c;内容变化已多单一的fragment&#xff0c;变成连续的&#xff0c;特别是以短视频或者直播为主的场景很多。从早起的Viewpage只能横向滑动&#xff0c;到如今的viewpage2可以支持横向或者竖向滑动。由于viewpage2的adapter在设计时支持缓…

预告 | 博睿数据将亮相第四届中国新能源汽车产业数智峰会

随着数字化、智能化浪潮的汹涌而至&#xff0c;全球汽车产业正站在一个崭新的历史起点上。新能源汽车&#xff0c;作为这场科技革命和产业变革的领跑者&#xff0c;其数智化发展正呈现出前所未有的蓬勃态势。正是在这样的背景下&#xff0c;第四届中国新能源汽车产业数智峰会将…

Windows 虚拟机服务器项目部署

目录 一、部署JDK下载JDK安装JDK1.双击 jdk.exe 安装程序2.点击【下一步】3.默认安装位置&#xff0c;点击【下一步】4.等待提取安装程序5.默认安装位置&#xff0c;点击【下一步】6.等待安装7.安装成功&#xff0c;点击【关闭】 二、部署TomcatTomcat主要特点包括&#xff1a;…

【线程安全】关于死锁问题

文章目录 死锁的基本概念死锁的四个必要条件避免死锁避免死锁的算法死锁检测算法 死锁的基本概念 死锁是指在一组进程中的各个进程均占有不会释放的资源&#xff0c;但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。当然&#xff0c;线程之间同样也有死…

【产品经理】WMS多仓调拨转移说明

对于仓储管理来说&#xff0c;越来越多企业开始应用WMS进行系统化的管理&#xff0c;以提升仓库的作业效率。本文作者从业务流程和基础功能两个方面展开介绍&#xff0c;希望对你有帮助。 一、业务流程 。在线下业务流程拓展&#xff0c;仓库不断增多的过程中&#xff0c;由于…

docker私有仓库harbor安装

Harbor默认安装 下载harbor https://github.com/goharbor/harbor/releases/download/v2.11.0/harbor-offline-installer-v2.11.0.tgz 目前要求docker版本&#xff0c;docker 20.10.10-ce &#xff0c;和docker-compose 1.18.0 查看 docker-compose版本 docker-compose --ver…

【Python】Python模块及常用模块介绍

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️Python】 文章目录 前言Python 模块(Module)模块的作用模块的创建模块的引入import 语句from…import 语句from…import* 语句 搜索路径常用模块[Python 标准库](https://docs.python.org/zh-cn/3/li…

Android中RecyclerView使用详解(一)

目录 概述优点列表布局RecyclerView一、创建RecyclerView并且在布局中绑定二、实现RecyclerView单个item的布局三、给RecyclerView写一个对应的适配器Adapter1.创建自定义的ViewHolder2.继承Adapter&#xff0c;泛型使用我们自定义的ViewHolder3.重写Adapter的三个方法onCreate…

STM32基础篇:EXTI × 事件 × EXTI标准库

EXTI EXTI简介 EXTI&#xff1a;译作外部中断/事件控制器&#xff0c;STM32的众多片上外设之一&#xff0c;能够检测外部输入信号的边沿变化并由此产生中断。 例如&#xff0c;在检测按键时&#xff0c;按键按下时会使电平产生翻转&#xff0c;因此可以使用EXTI来读取按下时…

Kotlin Misk Web框架

Kotlin Misk Web框架 1 Misk 框架介绍2 Misk/SpringBoot 框架对比3 Misk 添加依赖/配置3.1 build.gradle.kts3.2 settings.gradle.kts3.3 gradle.properties 4 Misk 请求接口5 Misk 程序模块6 Misk 主服务类7 Misk 测试结果 1 Misk 框架介绍 Misk 是由 Square 公司开发的一个开…

Python:while循环

while循环体 while 条件: 符合条件执行语句 .... 执行完后需执行的语句 # while循环 i1 while i<5:print(i)ii1 print("Done") test. 做一颗圣诞树吧 答案&#xff1a; # while循环 i 1 j5 while i < 5:print( * j* * i)i i 2jj-1 print("Done"…

【Python百日进阶-Web开发-音频】Day702 - librosa安装及模块一览表

文章目录 一、Librosa简介与安装1.1 Librosa是什么1.2 Librosa官网 二、Librosa安装2.1 安装Librosa 三、安装ffmpeg3.1 ffmpeg官网下载3.2 ffmpeg安装3.2.1 解压3.2.2 添加环境变量3.2.3 测试ffmpeg是否安装成功 四、Librosa 库模块一览4.1 库函数结构4.2 Audio processing&am…

Redis-linux下安装redis7配置

Redis安装配置 Redis安装配置一、Linux环境安装Redis必须先具备gcc编译环境1.什么是gcc 二、版本选择三、Redis7安装步骤1.下载2./opt目录下解压redis3.执行make命令4.查看默认安装目录:usr/local/bin5.初始化设置redis.conf6.启动服务7.连接服务8.关闭服务9.卸载redis Redis安…

方便好用的C#.Net万能工具库Masuit.Tools

文章目录 简介开发环境安装使用特色功能示例代码1. 检验字符串是否是Email、手机号、URL、IP地址、身份证号等2.硬件监测(需要管理员权限&#xff0c;仅支持Windows&#xff0c;部分函数仅支持物理机模式)3.html的防XSS处理&#xff1a;4.整理Windows系统的内存&#xff1a;5.任…

施耐德EOCR系列电机保护器全面升级后無端子型

一、施耐德数码型产品升级背景 施耐德电气作为一家全球领先的能源管理和自动化解决方案提供商&#xff0c;其产品线包括各种电动机保护器等数码型产品。随着技术的不断发展和市场需求的变化&#xff0c;施耐德会对其产品进行定期升级和优化。在升级过程中&#xff0c;产品的设…

前后端通信 —— HTTP/HTTPS

目录 一、HTTP/HTTPS 简介 1、HTTP 2、HTTPS 二、HTTP 工作过程 三、HTTP 消息 1、HTTP消息结构 2、HTTP消息示例 四、HTTP 方法&#xff08;常用&#xff09; 1、GET 2、POST 3、PUT 4、DELETE 5、GET与POST对比 五、HTTP 状态码&#xff08;常用&#xff09; …

Linux多线程编程-生产者与消费者模型详解与实现(C语言)

1.什么是生成者与消费者模型 生产者-消费者模型是并发编程中的经典问题&#xff0c;描述了多个线程&#xff08;或进程&#xff09;如何安全、有效地共享有限的缓冲区资源。在这个模型中&#xff0c;有两种角色&#xff1a; 生产者&#xff08;Producer&#xff09;&#xff1…