【C++】list的使用(上)

在这里插入图片描述

🔥个人主页: Forcible Bug Maker
🔥专栏: STL || C++

目录

  • 前言
  • 🌈关于list
  • 🔥默认成员函数
    • ==构造函数(constructor)==
    • ==析构函数(destructor)==
    • ==赋值运算符重载==
  • 🔥迭代器接口(Iterators)
  • 🔥容量获取接口(Capacity)
    • ==empty和size==
  • 🔥元素获取(Element access)
  • 🔥修改器(Modifiers)
    • ==assign==
    • ==push_back,pop_back,push_front和pop_front==
    • ==insert==
    • ==erase==
    • ==resize==
    • ==clear==
  • 结语

前言

本篇博客主要内容:STL库中list的介绍以及list用法的讲解

我们已经知道,stringvector的底层都是简单的顺序表,而list的底层就和之前的两个大不相同了,list的底层是一个带头双向循环链表。学习list之前,如果你还不知道什么是链表,完全由必要学习一下,可以看看我初阶数据结构所讲到的内容:初阶数据结构-顺序表和链表(C语言)

在C++中,我们可以直接使用list创建链表。

🌈关于list

在这里插入图片描述
list是可以在常数范围内任意位置进行插入和删除的序列式容器,并且可以前后双向迭代。

list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针向其前一个元素和后一个元素。

list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已经让其更简单更高效。

与其他序列式容器相比(array,vector,deque),list通常在任意位置进行插入,移除元素的执行效率更好。

于其他序列式容器相比,list和forward_list最大的缺陷是不支持元素的随机访问,比如:需要访问list的第六个元素,必须从已有的位置(比如头部或尾部)迭代到该位置,这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个结点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)。

🔥默认成员函数

在这里插入图片描述

构造函数(constructor)

在这里插入图片描述

注:对于最后一个参数(alloc),可以不用深究,在后期学了内存池相关的内容后会细讲。

构造一个list容器对象,可以根据以下四种方式初始化:
default (1)

explicit list (const allocator_type& alloc = allocator_type());

这是std::list无参构造。它创建了一个不含任何元素的空list对象。其中explicit关键字阻止了隐式类型转换。

fill (2)

explicit list (size_type n, const value_type& val = value_type(),
               const allocator_type& alloc = allocator_type());

构造一个含有n个val值得list对象

range (3)

template <class InputIterator>
  list (InputIterator first, InputIterator last,
         const allocator_type& alloc = allocator_type());

按迭代器区间[first, last) 的内容顺序构造list对象

copy (4)

list (const list& x);

构造一个x对象得拷贝
允许隐式类型转换。

代码案例:

// constructing lists
#include <iostream>
#include <list>

int main()
{
    // constructors used in the same order as described above:
    std::list<int> first;                                // 构建数据类型为整型的一个空链表
    std::list<int> second(4, 100);                       // 构建一个包含四个值为100的链表
    std::list<int> third(second.begin(), second.end());  // 通过second链表的迭代器构建third
    std::list<int> fourth(third);                       // 用third拷贝一个相同的链表fourth

    // the iterator constructor can also be used to construct from arrays:
    int myints[] = { 16,2,77,29 };
    std::list<int> fifth(myints, myints + sizeof(myints) / sizeof(int));

    std::cout << "The contents of fifth are: ";
    for (std::list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)
        std::cout << *it << ' ';

    std::cout << '\n';

    return 0;
}

在这里插入图片描述

析构函数(destructor)

在这里插入图片描述
析构函数是当编译器出了对象的生命周期时自动调用的默认成员函数,释放开辟的内存空间

赋值运算符重载

在这里插入图片描述

通过已有对象给被操作对象分配新的值,覆盖它原来的内容,并根据内容调整size的大小。

 list& operator= (const list& x);

从x中拷贝所有的内容到被操作list对象中
在调用之前容器中持有的任何元素都将被分配给新值或被销毁。

代码案例:

// assignment operator with lists
#include <iostream>
#include <list>

int main()
{
	std::list<int> first(3);      // list of 3 zero-initialized ints
	std::list<int> second(5);     // list of 5 zero-initialized ints

	second = first;
	first = std::list<int>();

	std::cout << "Size of first: " << int(first.size()) << '\n';
	std::cout << "Size of second: " << int(second.size()) << '\n';
	return 0;
}

两个包含整型元素的列表容器都被初始化为不同大小的序列。然后,second容器被first容器赋值,所以现在两个容器相等并且大小都是3。接着,first容器被赋值给一个新构造的空容器对象(匿名对象),因此它的大小最终变为0。
在这里插入图片描述

🔥迭代器接口(Iterators)

在这里插入图片描述
对于STL的各种容器,迭代器的规则都是极其相似的。

和vector和string相同,begin获取指向list对象首元素的迭代器,end指向链表尾元素下一位的迭代器。

我认为迭代器在vector和string的基础上可以直接上代码了,大家能直接了解其用法。

代码案例:

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

int main()
{
	list<int> lt({ 1,2,3,4 });
	
	// 获取正向迭代器遍历
	list<int>::iterator it = lt.begin();
	while (it != lt.end()) {
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// 获取反向迭代器遍历
	list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend()) {
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

	return 0;
}

在这里插入图片描述
不过在使用list迭代器需要特别注意的一点:list链表的迭代器不支持加减运算,只支持++和- -运算符,如it += 1it = it + 3的写法会使编译器报错。

🔥容量获取接口(Capacity)

在这里插入图片描述

empty和size

bool empty() const;

判断list对象是否为空

size_type size() const;

获取list对象元素个数

代码案例:

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

int main()
{
	list<int> lt1;
	list<int> lt2({ 1,2,3,4 });

	cout << "lt1.empty():" << lt1.empty() << endl;
	cout << "lt2.empty():" << lt2.empty() << endl;
	cout << endl;

	cout << "lt1.size():" << lt1.size() << endl;
	cout << "lt2.size():" << lt2.size() << endl;

	return 0;
}

在这里插入图片描述

🔥元素获取(Element access)

在这里插入图片描述

  reference front();
const_reference front() const;

获取list对象首元素

reference back();
const_reference back() const;

获取list对象尾元素

代码案例:

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

int main()
{
	list<int> lt({ 1,2,3,4 });

	cout << lt.front() << endl;
	cout << lt.back() << endl;

	return 0;
}

在这里插入图片描述

🔥修改器(Modifiers)

在这里插入图片描述

assign

在这里插入图片描述
range (1)

template <class InputIterator>
  void assign (InputIterator first, InputIterator last);

fill (2)

void assign (size_type n, const value_type& val);

两个重载都可以给list对象分配新内容,将对象原有的内容覆盖。

代码案例:

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

int main()
{
	list<int> lt1({ 1,2,3,4 });
	list<int> lt2({ 0,0,0,0 });

	lt1.assign(lt2.begin(), lt2.end());
	for (auto e : lt1) {
		cout << e << " ";
	}
	cout << endl;

	lt1.assign(8, -1);
	for (auto e : lt1) {
		cout << e << " ";
	}
	return 0;
}

在这里插入图片描述

push_back,pop_back,push_front和pop_front

分别对应着链表的尾插尾删和头插头删

代码案例:

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

int main()
{
	list<int> lt({ 0,0,0 });

	for (auto e : lt) {cout << e << " ";}
	cout << endl;

	lt.push_back(-1);
	for (auto e : lt) { cout << e << " "; }
	cout << endl;

	lt.pop_back();
	for (auto e : lt) { cout << e << " "; }
	cout << endl;

	lt.push_front(-1);
	for (auto e : lt) { cout << e << " "; }
	cout << endl;

	lt.pop_front();
	for (auto e : lt) { cout << e << " "; }
	cout << endl;

	return 0;
}

在这里插入图片描述

insert

在这里插入图片描述
single element (1)

iterator insert (iterator position, const value_type& val);

在迭代器指向元素之前插入val。
fill (2)

void insert (iterator position, size_type n, const value_type& val);

在迭代器指向元素之前插入n个val。
range (3)

template <class InputIterator>
    void insert (iterator position, InputIterator first, InputIterator last);

在迭代器指向元素之前按顺序插入迭代器区间[first, last)内的值。

带吗案例:

#include <iostream>
#include <list>
#include <vector>

int main()
{
    std::list<int> mylist;
    std::list<int>::iterator it;

    // set some initial values:
    for (int i = 1; i <= 5; ++i) mylist.push_back(i); // 1 2 3 4 5

    it = mylist.begin();
    ++it;       // it points now to number 2           ^

    mylist.insert(it, 10);                        // 1 10 2 3 4 5

    // "it" still points to number 2                      ^
    mylist.insert(it, 2, 20);                      // 1 10 20 20 2 3 4 5

    --it;       // it points now to the second 20            ^

    std::vector<int> myvector(2, 30);
    mylist.insert(it, myvector.begin(), myvector.end());
    // 1 10 20 30 30 20 2 3 4 5
    //               ^
    std::cout << "mylist contains:";
    for (it = mylist.begin(); it != mylist.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    return 0;
}

在这里插入图片描述

erase

在这里插入图片描述

iterator erase (iterator position);
iterator erase (iterator first, iterator last);

删除list容器中一个迭代器(position)指向的元素或者一段迭代器区间(first, last]内的元素
返回值为指向被删除元素下一元素的迭代器

代码案例:

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

int main()
{
	list<int> lt({ 1,2,3,4,5 });
	for (auto e : lt) { cout << e << " "; }
	cout << endl;

	list<int>::iterator it = lt.begin();
	++it;
	it = lt.erase(it);
	for (auto e : lt) { cout << e << " "; }
	cout << endl;

	it = lt.erase(it, lt.end());
	for (auto e : lt) { cout << e << " "; }
	cout << endl;

	return 0;
}

在这里插入图片描述

resize

void resize (size_type n, value_type val = value_type());

此接口函数用于调整容器的大小,使其包含n个元素。
如果n小于当前容器的大小,内容将被缩减为其前n个元素,移除超出n的部分(并销毁它们)。
如果n大于当前容器的大小,内容将通过在末尾插入所需数量的新元素来扩展,以达到大小为n。如果指定了val,新元素将被初始化为val的副本;否则,它们将进行默认值初始化。

// resizing list
#include <iostream>
#include <list>

int main()
{
    std::list<int> mylist;

    // set some initial content:
    for (int i = 1; i < 10; ++i) mylist.push_back(i);

    mylist.resize(5);
    mylist.resize(8, 100);
    mylist.resize(12);

    std::cout << "mylist contains:";
    for (std::list<int>::iterator it = mylist.begin(); it != mylist.end(); ++it)
        std::cout << ' ' << *it;

    std::cout << '\n';

    return 0;
}

在这里插入图片描述

clear

void clear();

从列表容器(其中的元素将被销毁)中移除所有元素,使size的大小变为0

结语

本篇博客给大家初步介绍了list,其底层是一个双向循环链表,讲解了list的一些函数接口,如修改器,元素访问,以及迭代器接口的使用方式。这些功能和规则和vector,string的接口大同小异,名称也大都一致,降低了我们的学习成本。
博主后续还会产出更多有关于STL的内容,感谢大家的支持。♥

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

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

相关文章

第十六课,海龟画图:设置画笔颜色、宽度函数,移动画笔函数

一&#xff0c;turtle.color()&#xff1a;画笔颜色函数 这个函数能设置画笔画出来的颜色&#xff0c;当然&#xff0c;使用它之前你需要认识有哪些“颜料”可供你选择&#xff0c;turtle库的color()函数可以选择以下颜色&#xff1a; "white" 白色&#xff08;建议…

进程间通信(27000字超详解)

&#x1f30e;进程间通信 文章目录&#xff1a; 进程间通信 进程间通信简介       进程间通信目的       初识进程间通信       进程间通信的分类 匿名管道通信       认识管道       匿名管道       匿名管道测试       管道的四种…

Linux系统编程(七)网络编程TCP、UDP

本文目录 一、基础知识点1. IP地址2. 端口3. 域名4. 网络协议类型5. IP协议类型6. 字节序7. socket套接字 二、常用API1. socket套接字描述符2. bind套接字绑定3. listen设置客户端连接个数4. accept接收客户端请求5. connect连接服务端 三、编程流程1.TCP编程 在学习本章之前&…

sqoop操作

介绍 sqoop是隶属于Apache旗下的, 最早是属于cloudera公司的,是一个用户进行数据的导入导出的工具, 主要是将关系型的数据库(MySQL, oracle...)导入到hadoop生态圈(HDFS,HIVE,Hbase...) , 以及将hadoop生态圈数据导出到关系型数据库中 操作 将数据从mysql中导入到HDFS中 1.全量…

[AI Google] Google I/O 2024: 为新一代设计的 I/O

编辑注&#xff1a;以下是 Sundar Pichai 在 I/O 2024 上讲话的编辑版&#xff0c;并包含了更多在舞台上宣布的内容。查看我们收藏中的所有公告。 Google 完全进入了我们的 Gemini 时代。 在开始之前&#xff0c;我想反思一下我们所处的这一刻。我们已经在 AI 上投资了十多年…

【LeetCode 101】对称二叉树

1. 题目 2. 分析 这道题比较经典。我又一次做错了&#xff0c;这次是花了20min都没有做出来。 最开始我的思想就是&#xff0c;递归比较左根节点的左子树和右根节点的右子树是否对称即可&#xff0c;然后觉得能解决问题了&#xff0c;便动手coding。哪知道&#xff0c;又碰到了…

23.Labview中的数值类型讨论 ---- 位(bit)、字节(byte)、I8、U8、单双精度、复数

hello&#xff0c;大家好&#xff0c;本篇向大家介绍一个最常用但最容易让人忽略和最容易犯错的知识&#xff1a;数值。 “数值” 这个概念在Labview中被涉及的还是很多的&#xff0c;几乎任何一个程序都无可避免的会用到&#xff0c;但我相信大家绝大多数人对数值这个概念应用…

CentOS8安装opensips 3.5

环境&#xff1a;阿里云 操作系统CentOS8.5 依赖包安装&#xff1a; libmicrohttpd cd /usr/local/src wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-latest.tar.gz tar vzxf libmicrohttpd-latest.tar.gz cd libmicrohttpd-1.0.1/./configure make make …

【CVPR_2024】:逐元素乘积为什么会产生如此令人满意的结果?

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言论文重写星形运算一层网络推广多层网络特殊情况 W 1 W_1 W1​和/或 W 2 W_2 W2​…

Python-3.12.0文档解读-内置函数sorted()详细说明+记忆策略+常用场景+巧妙用法+综合技巧

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 Python-3.12.0文档解读详细说明 功能描述 参数说明 用法示例 备注 进阶用法 参考…

集合操作进阶:关于移除列表元素的那点事

介绍 日常开发中&#xff0c;难免会对集合中的元素进行移除操作&#xff0c;如果对这方面不熟悉的话&#xff0c;就可能遇到 ConcurrentModificationException&#xff0c;那么&#xff0c;如何优雅地进行元素删除&#xff1f;以及其它方式为什么不行&#xff1f; 数据初始化…

力扣--双指针15.三数之和

详细思路 排序数组&#xff1a;首先对数组 nums 进行排序&#xff0c;目的是为了方便后续使用双指针查找和避免重复结果。遍历数组&#xff1a;使用一个 for 循环从头遍历到倒数第三个元素。i 表示当前固定的元素。 跳过重复元素&#xff1a;如果当前元素 nums[i] 与前一个元素…

使用matplotlib绘制折线条形复合图

使用matplotlib绘制折线条形复合图 介绍效果代码 介绍 在数据可视化中&#xff0c;复合图形是一种非常有用的工具&#xff0c;可以同时显示多种数据类型的关系。在本篇博客中&#xff0c;我们将探讨如何使用 matplotlib 库来绘制包含折线图和条形图的复合图。 效果 代码 imp…

登录安全分析报告:小米官网注册

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

【算法】模拟算法——数青蛙(medium)

题解&#xff1a;模拟算法——数青蛙(medium) 目录 1.题目2.题解3.参考代码4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 用循环进行遍历&#xff0c; 如果该字符为o\o\a\k 找一下前驱字符是否存在 如果存在&#xff0c;前驱字符–&#xff0c;该字符如果不存在&#x…

STM32_IIC

1、IIC简介 I2C&#xff0c;即Inter IC Bus。是由Philips公司开发的一种串行通用数据总线&#xff0c;主要用于近距离、低速的芯片之间的通信&#xff1b;有两根通信线&#xff1a;SCL&#xff08;Serial Clock&#xff09;用于通信双方时钟的同步、SDA&#xff08;Serial Data…

echarts渐变色与css渐变色互转(两个坐标点转角度)

前言 用于 echarts 的小伙伴都知道&#xff0c;他使用的渐变色写法和 css 的写法不一样。css 中直接使用角度定义渐变的方向&#xff0c;而 echarts 使用的是两个坐标点来进行标识方向&#xff08;线性渐变&#xff09;。 本文主要针对线性渐变的转换 那怎么在 css 中使用 e…

BrainGPT1,一个帮你b站点歌放视频的多模态多轮对话模型

BrainGPT1&#xff0c;一个帮你b站点歌放视频的多模态多轮对话模型 返回论文目录 项目地址 模型地址 作者&#xff1a;华东师范大学&#xff0c;计算机科学与技术学院&#xff0c;智能教育研究院的小怪兽会微笑。 介绍 BrainGPT1是一个工具调用多轮对话模型&#xff0c;与G…

[机器学习]GPT LoRA 大模型微调,生成猫耳娘

往期热门专栏回顾 专栏描述Java项目实战介绍Java组件安装、使用&#xff1b;手写框架等Aws服务器实战Aws Linux服务器上操作nginx、git、JDK、VueJava微服务实战Java 微服务实战&#xff0c;Spring Cloud Netflix套件、Spring Cloud Alibaba套件、Seata、gateway、shadingjdbc…

BU01板卡引脚

概述 BU01 是一款高速采集卡&#xff0c;主要用于高带宽数据采集及传输&#xff0c;应用领域多为数据中 心及数据采集领域。 端口提供60Gbps 传输带宽&#xff0c;可兼容2 个SFP万兆网口&#xff0c;和1 个40GE QSFP 光 口。和主机通信采用的是PCIE 2.0 x8 模式&#xff0c;最…