(C++)STL:list认识与使用全解析

本篇基于https://cplusplus.com/reference/list/list/讲解

认识

list是一个带头结点的双向循环链表
在这里插入图片描述
翻译总结:

  1. 序列容器:list是一种序列容器,允许在序列的任何位置进行常数时间的插入和删除操作。
  2. 双向迭代:list支持双向迭代,即可以向前和向后遍历元素。
  3. 双链表实现:list容器内部通过双链表实现。每个元素都包含指向前一个元素和后一个元素的链接。
  4. 非连续存储:与数组或vector不同,list中的元素可以存储在不同的、不连续的内存位置。
  5. 内存开销:由于需要额外的内存来存储每个元素的链接信息,list相对于数组或vector会消耗更多的内存。
  6. 与forward_list的区别:list与forward_list相似,但forward_list是单链表,只能单向迭代,而list是双链表,可以双向迭代。
  7. 插入和删除性能:与其他标准序列容器(如array、vector和deque)相比,list在已知迭代器位置的容器内插入、提取和移动元素时表现更好,尤其是在需要频繁修改序列内容的情况下。
  8. 访问性能:与array、vector和deque相比,list的主要缺点是缺乏通过位置直接访问元素的能力。访问特定位置的元素需要从已知位置(如序列的开始或结束)开始迭代,这需要线性时间。
  9. 适用场景:list适用于需要频繁在序列中间插入和删除元素的场景,以及需要双向迭代的场景。对于需要频繁访问特定位置元素的场景,list可能不是最佳选择。

接口

在string、vector的基础上不作过多说明,仅强调差异的内容

遍历

由于底层不是数组,由其访问性能得知( 访问性能:与array、vector和deque相比,list的主要缺点是缺乏通过位置直接访问元素的能力。访问特定位置的元素需要从已知位置(如序列的开始或结束)开始迭代,这需要线性时间。)
不再支持operator[],只支持迭代器遍历和范围for。

// list::begin
#include <iostream>
#include <list>int main ()
{int myints[] = {75,23,65,42,13};std::list<int> mylist (myints,myints+5);std::cout << "mylist contains:";for (std::list<int>::iterator it=mylist.begin(); it != mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

支持头删、头插

在这里插入图片描述

string、vector这两个底层是数组的结构进行头删会导致大量的数据挪动,所以尽量避免头插头删,只在必要时使用insert实现,但对于list,不会产生大量挪动消耗,因此有单独的头插头删函数。

容量操作

在这里插入图片描述
没有reserve,因为list是一个一个结点开辟、一个一个结点删除的

额外增加的链表相关接口

在这里插入图片描述

remove 删除特定的值

注意其与erase的区别
在这里插入图片描述

// remove from list
#include <iostream>
#include <list>int main ()
{int myints[]= {17,89,7,14};std::list<int> mylist (myints,myints+4);mylist.remove(89);std::cout << "mylist contains:";for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

在这里插入图片描述

remove_if 条件删除

merge 归并

两个有序list合并以后仍然有序
在这里插入图片描述

(1)void merge(list<T>& x);
(2)使用自定义比较函数:void merge(list<T>& x, Compare comp);
这里,x 是要合并到当前列表的另一个列表,comp 是一个自定义的比较函数,它接受两个参数并返回一个布尔值,指示第一个参数是否应该在第二个参数之前。

#include <iostream>
#include <list>// 自定义的比较函数
bool mycomparison (double first, double second)
{ return ( int(first)<int(second) ); }int main ()
{std::list<double> first, second;first.push_back (3.1);first.push_back (2.2);first.push_back (2.9);second.push_back (3.7);second.push_back (7.1);second.push_back (1.4);//先让两个列表是有序的first.sort();second.sort();
//(1)first.merge(second);// (second is now empty)合并后second变为空second.push_back (2.1);
//(2)first.merge(second,mycomparison);std::cout << "first contains:";for (std::list<double>::iterator it=first.begin(); it!=first.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

在这里插入图片描述

unique 去重

前提是有序的list!!原因和去重函数的底层实现有关

// list::unique
#include <iostream>
#include <cmath>
#include <list>// a binary predicate implemented as a function:
bool same_integral_part (double first, double second)
{ return ( int(first)==int(second) ); }// a binary predicate implemented as a class:
struct is_near {bool operator() (double first, double second){ return (fabs(first-second)<5.0); }
};int main ()
{double mydoubles[]={ 12.15,  2.72, 73.0,  12.77,  3.14,12.77, 73.35, 72.25, 15.3,  72.25 };std::list<double> mylist (mydoubles,mydoubles+10);mylist.sort();             //  2.72,  3.14, 12.15, 12.77, 12.77,// 15.3,  72.25, 72.25, 73.0,  73.35mylist.unique();           //  2.72,  3.14, 12.15, 12.77// 15.3,  72.25, 73.0,  73.35mylist.unique (same_integral_part);  //  2.72,  3.14, 12.15// 15.3,  72.25, 73.0mylist.unique (is_near());           //  2.72, 12.15, 72.25std::cout << "mylist contains:";for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

在这里插入图片描述

sort

默认排升序

  • 为什么标准库里有sort,且vector都没有单独实现sort,list却要单独实现?

在这里插入图片描述

  1. 迭代器按功能分类为单向、双向、随机迭代器,分类由容器的底层结构决定,底层连续存储的,更好支持加减
  2. 三种迭代器有兼容关系:要求单向,可以用双向和随机,要求双向,可以用随机。
    包含大小:随机>双向>单向
  3. 算法的迭代器类型参数名字,暗示了其需要的迭代器类型要求
    std::sort需要随机迭代器,而list的迭代器是双向迭代器,所以list无法使用标准库的sort
    reverse需要双向迭代器,find需要只读迭代器InputIterator(实际上代表单向、双向、随机迭代器都可以)

在这里插入图片描述

  • 这个成员函数sort效率如何?
    效率远不如std::sort。所以数据多的时候尽量不要使用这个sort
    当数据量为1000000时,拷贝到vector去排序再拷贝回来,vector的性能都好很多。
    在这里插入图片描述

reverse 反转

在这里插入图片描述

splice 粘贴

把一个链表中的数据转移到另一个链表里去
在这里插入图片描述
注意list迭代器要求是双向迭代器,无法通过begin()+几或-几来控制位置

// splicing lists
#include <iostream>
#include <list>int main ()
{std::list<int> mylist1, mylist2;std::list<int>::iterator it;// set some initial values:for (int i=1; i<=4; ++i)mylist1.push_back(i);      // mylist1: 1 2 3 4for (int i=1; i<=3; ++i)mylist2.push_back(i*10);   // mylist2: 10 20 30it = mylist1.begin();++it;                         // points to 2mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4// mylist2 (empty)// "it" still points to 2 (the 5th element)mylist2.splice (mylist2.begin(),mylist1, it);// mylist1: 1 10 20 30 3 4// mylist2: 2// "it" is now invalid.it = mylist1.begin();std::advance(it,3);           // "it" points now to 30mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());// mylist1: 30 3 4 1 10 20
//实现一个list中的元素调整————输入该list的迭代器std::cout << "mylist1 contains:";for (it=mylist1.begin(); it!=mylist1.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';std::cout << "mylist2 contains:";for (it=mylist2.begin(); it!=mylist2.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

在这里插入图片描述

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

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

相关文章

Bash函数详解

目录**1. 基础函数****2. 参数处理函数****3. 文件操作函数****4. 日志与错误处理****5. 实用工具函数****6. 高级函数技巧****7. 常用函数库示例****总结&#xff1a;Bash 函数核心要点**1. 基础函数 1.1 定义与调用 可以自定义函数名称&#xff0c;例如将greet改为yana。❌…

Python爬虫实战:研究rows库相关技术

1. 引言 在当今数字化时代,互联网上存在着大量有价值的表格数据,这些数据以 HTML 表格、CSV、Excel 等多种格式存在。然而,由于数据源的多样性和不规范性,表格结构往往存在复杂表头、合并单元格、不规则数据行等问题,给数据的自动化处理带来了巨大挑战。 传统的数据处理工…

通过同态加密实现可编程隐私和链上合规

1. 引言 2023年9月28日&#xff0c;a16z 的加密团队发布了 Nakamoto Challenge&#xff0c;列出了区块链中需要解决的最重要问题。尤其是其中的第四个问题格外引人注意&#xff1a;“合规的可编程隐私”&#xff0c;因为Zama团队已经在这方面积极思考了一段时间。本文提出了使…

封装---统一封装处理页面标题

一.采用工具来实现(setPageTitle.ts)多个页面中用更统一的方式设置 document.title&#xff0c;可以封装一个工具函数:在utils目录下新建文件:setPageTitle.ts如果要在每个页面设置相同的网站标志可以使用下面的appNameconst appName: string import.meta.env.VITE_APP_NAMEex…

JAVA学习笔记 首个HelloWorld程序-002

目录 1 前言 2 开发首个程序 3 小结 1 前言 在所有的开发语言中&#xff0c;基本上首先程序就是输出HelloWorld&#xff0c;这里也不例外。这个需要注意的是&#xff0c;程序的核心功能是数据输出&#xff0c;是要有一个结果&#xff0c;可能没有输入&#xff0c;但是一定有…

智慧监所:科技赋能监狱管理新变革

1. 高清教育&#xff1a;告别模糊画面&#xff0c;学习更清晰传统电视的雪花屏终于成为历史&#xff01;新系统采用高清传输&#xff0c;课件文字清晰可见&#xff0c;教学视频细节分明。某监狱教育科王警官说&#xff1a;"现在播放法律课程&#xff0c;服刑人员能清楚看到…

专题:2025供应链数智化与效率提升报告|附100+份报告PDF、原数据表汇总下载

全文链接&#xff1a;https://tecdat.cn/?p42926 在全球产业链重构与数字技术革命的双重驱动下&#xff0c;供应链正经历从传统经验驱动向数据智能驱动的范式变革。从快消品产能区域化布局到垂类折扣企业的效率竞赛&#xff0c;从人形机器人的成本优化到供应链金融对中小企业的…

uniapp+vue3+ts项目:实现小程序文件下载、预览、进度监听(含项目、案例、插件)

uniapp+vue3+ts项目:实现小程序文件下载、预览、进度监听(含项目、案例、插件) 支持封装调用: 项目采用uniapp+vue3+ts +京东nutUI 开发nutUi文档:loadingPage组件:https://uniapp-nutui.tech/components/exhibition/loadingpage.html案例效果图: 略博主自留地:参考本地…

用Python和OpenCV从零搭建一个完整的双目视觉系统(六 最终篇)

本系列文章旨在系统性地阐述如何利用 Python 与 OpenCV 库&#xff0c;从零开始构建一个完整的双目立体视觉系统。 本项目github地址&#xff1a;https://github.com/present-cjn/stereo-vision-python.git 1. 概述 欢迎来到本系列文章的最后一篇。在过去的几篇文章中&#…

Android View 绘制流程 简述 (无限递归+BitMap问题)

绘制流程 在 Android 的 View 系统中&#xff0c;draw(canvas) 和 dispatchDraw(canvas) 是绘制流程中的两个关键方法&#xff1a; 1. draw(canvas) 方法的作用 draw(canvas) 是 View 类中的核心绘制方法&#xff0c;它的主要职责包括&#xff1a; 绘制背景 - 调用 drawBac…

算法学习笔记:18.拉斯维加斯算法 ——从原理到实战,涵盖 LeetCode 与考研 408 例题

在随机化算法领域&#xff0c;拉斯维加斯&#xff08;Las Vegas&#xff09;算法以其独特的设计思想占据重要地位。与蒙特卡洛&#xff08;Monte Carlo&#xff09;算法不同&#xff0c;拉斯维加斯算法总能给出正确的结果&#xff0c;但运行时间具有随机性 —— 在最坏情况下可…

26-计组-指令执行过程

一、指令周期1. 定义与组成定义&#xff1a;CPU取出并执行一条指令所需的全部时间&#xff0c;称为指令周期。子周期划分&#xff1a;取指周期&#xff08;必选&#xff09;&#xff1a;从存储器取指令到指令寄存器&#xff08;IR&#xff09;。间址周期&#xff08;可选&#…

【JMeter】数据驱动测试

文章目录创建数据文件加载数据文件根据数据文件请求接口、传递参数拓展含义&#xff1a;根据数据的数量、内容&#xff0c;自动的决定用例的数据和内容。数据驱动测试用例。步骤&#xff1a; 创建数据文件加载数据文件根据数据文件请求接口、传递参数 创建数据文件 Jmeter支…

Springboot实现一个接口加密

首先来看效果这个主要是为了防止篡改请求的。 我们这里采用的是一个AOP的拦截&#xff0c;在有需要这样的接口上添加了加密处理。 下面是一些功能防篡改HMAC-SHA256 参数签名密钥仅客户端 & 服务器持有防重放秒级时间戳 有效窗口校验默认允许 5 分钟防窃听AES/CBC/PKCS5Pa…

斯坦福 CS336 动手大语言模型 Assignment1 BPE Tokenizer TransformerLM

所有代码更新至 https://github.com/WangYuHang-cmd/CS336/tree/main/assignment1-basics 作业文件结构: CS336/assignment1-basics/ ├── tests/ # 测试文件目录 │ ├── adapters.py # 适配器测试 │ ├── conftest.py # pyt…

Spring Cloud Gateway 实战指南

关键词&#xff1a;微服务、API网关、Spring Cloud Gateway、路由转发、限流熔断 ✅ 文章摘要 随着互联网应用规模的不断扩大&#xff0c;传统的单体架构逐渐向微服务架构转型。在微服务架构中&#xff0c;API 网关作为系统的入口点&#xff0c;承担了诸如请求路由、负载均衡、…

PyTorch自动微分:从基础到实战

目录 1. 自动微分是什么&#xff1f; 1.1 计算图 1.2 requires_grad 属性 2. 标量和向量的梯度计算 2.1 标量梯度 2.2 向量梯度 3. 梯度上下文控制 3.1 禁用梯度计算 3.2 累计梯度 4. 梯度下降实战 4.1 求函数最小值 4.2 线性回归参数求解 5. 总结 在深度学习中&a…

Spring AI 项目实战(十六):Spring Boot + AI + 通义万相图像生成工具全栈项目实战(附完整源码)

系列文章 序号文章名称1Spring AI 项目实战(一):Spring AI 核心模块入门2Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码)3Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码)4

从零到一:企业如何组建安全团队

在这个"黑客满天飞&#xff0c;漏洞遍地跑"的时代&#xff0c;没有安全团队的企业就像裸奔的勇士——虽然很有勇气&#xff0c;但结局往往很悲惨。 &#x1f4cb; 目录 为什么要组建安全团队安全团队的核心职能团队架构设计人员配置策略技术体系建设制度流程建立实施…

业务访问控制-ACL与包过滤

业务访问控制-ACL与包过滤 ACL的定义及应用场景ACL&#xff08;Access Control List&#xff0c;访问控制列表&#xff09;是用来实现数据包识别功能的&#xff1b;ACL可以应用于诸多场景&#xff1a; 包过滤功能&#xff1a;对数据包进行放通或过滤操作。NAT&#xff08;Netwo…