【C++STL】list的基本介绍与使用方式

embedded/2024/10/22 5:30:32/


Blog’s 主页: 白乐天_ξ( ✿>◡❛)
🌈 个人Motto:他强任他强,清风拂山冈!
🔥 所属专栏:C++深入学习笔记
💫 欢迎来到我的学习笔记

list_11">一、list的介绍

文档内容以及大致翻译如下图:

  1. list是一种允许在序列内的任何位置进行常数时间的插入删除的序列式容器,并且该容器可以前后双向的迭代;
  2. list的底层是一个带头双向循环链表,双向链表中每个元素存储在不相关的独立结点中,在结点中通过指针指向前一个位置和后一个位置;
  3. listforward_list非常相似,最主要的区别在于:forward_list是单链表,只能进行单方向的迭代;
  4. 与其他容器相比,list通常在任意位置进行插入、删除元素的执行效率更高;
  5. listforward_list最大的缺点就是:不支持在任意位置的随机访问;其次list还需要一些额外的空间来保存每个结点之间的关联信息(对于存储的类型较小的元素的链表来说这可能是一个很重要的因素)。

list_25">二、list的使用

list_26">2.1.list的定义方式

#include <list>
#include <string>
using namespace std;
int main()
{// 1. 构造某个类型的空容器list<int> lt1;// 构造int类型的空容器// 2. 构造一个含有val的某类型容器list<int> lt2(10, 2);// 构造含有10个2的int类型容器// 3. 构造某类型容器的复制品list<int> lt3(lt2);// 拷贝哦构造int类型的lt2容器的复制品// 4. 使用迭代器构造某一段内容string s("hello world");list<char> lt4(s.begin(), s.end());// 构造string对象某段区间的复制品// 5. 构造数组某段区间的复制品int arr[] = { 1,2,3,4 };int sz = sizeof(arr) / sizeof(int);list<int> lt5(arr, arr + sz);// 构造数组某段区间的复制品return 0;
}

list_55">2.2.list的插入删除

2.2.1.push_front(头插)和pop_front(头删)

push_front函数用于头插一个数据,pop_front函数用于头删一个数据。

#include <list>
#include <string>
#include <iostream>
using namespace std;int main()
{list<int> lt;lt.push_front(0);lt.push_front(1);lt.push_front(2);lt.push_front(3);for (auto e : lt){cout << e << " ";}cout << endl;lt.pop_front();for (auto e : lt){cout << e << " ";}cout << endl;lt.pop_front();for (auto e : lt){cout << e << " ";}cout << endl;return 0;
}

2.2.2.push_back(尾插)和pop_back(尾删)

push_back函数用于尾插一个数据,pop_back用于尾删一个数据。

#include <list>
#include <iostream>
using namespace std;
int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);for (auto e : lt){cout << e << " ";}cout << endl;cout << endl;lt.pop_back();for (auto e : lt){cout << e << " ";}cout << endl;return 0;
}

2.2.3.insert

insert的使用形式:

// 在指定迭代器位置插入一个数
iterator insert (iterator position, const value_type& val);
// 在指定迭代器位置插入n个值为val的数void insert (iterator position, size_type n, const value_type& val);
// 在指定迭代器位置插入一段迭代器区间(左闭右开)
template <class InputIterator>void insert (iterator position, InputIterator first, InputIterator last);

代码举例:

#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
using namespace std;int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);// 用法一:在指定迭代器位置插入一个数据list<int>::iterator pos = find(lt.begin(), lt.end(), 2);// 找到数据2的位置,下标赋值给poslt.insert(pos, 10);// 在2的位置插入10for (auto e : lt){cout << e << " ";}cout << endl;// 用法二:再制定迭代器位置插入n个值为val的数据pos = find(lt.begin(), lt.end(), 3);// 找到数据的位置,下标赋值给poslt.insert(pos, 3, 9);// 在pos的位置插入3个9for (auto e : lt){cout << e << " ";}cout << endl;// 用法三:在指定迭代器位置插入一段迭代器区间(左闭右开)vector<int> v(2, 7);//pos = find(lt.begin(), lt.end(), 1);// 找到1的位置,下标赋值给poslt.insert(pos, v.begin(), v.end());// 在1的位置插入一个迭代器区间的数据(2个7)for (auto e : lt){cout << e << " ";}cout << endl;return 0;
}

补充:find函数的头文件algorithm,该函返回一个迭代器,指向<font style="color:rgb(42, 43, 46);">[first,last)</font>范围内第一个与val相等的元素。如果没有找到这样的元素,则返回<font style="color:rgb(42, 43, 46);">last</font>

template <class InputIterator, class T>InputIterator find (InputIterator first, InputIterator last, const T& val);
// val就是要查找的值

2.2.4.erase

erase的使用形式:

// 删除指定迭代器位置的元素
iterator erase (iterator position);
// 删除指定迭代器区间(左闭右开)的所有元素
iterator erase (iterator first, iterator last);

代码示例:

#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
using namespace std;int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);for (auto e : lt){cout << e << " ";}cout << endl;// 1 2 3 4 5// erase的第一个用法:list<int>::iterator pos = find(lt.begin(), lt.end(), 2);// 在迭代器区间查找2lt.erase(pos);//删除pos位置的值——2for (auto e : lt){cout << e << " ";}cout << endl;// 1 3 4 5// erase的第二个用法:pos = find(lt.begin(), lt.end(), 4);lt.erase(pos, lt.end());// 删除pos之后的所有数据——删除4、5for (auto e : lt){cout << e << " ";}cout << endl;// 1 3 return 0;
}

list_252">2.3.list的迭代器使用

2.3.1.begin和end

正向迭代器遍历容器

#include <vector>
#include <list>
#include <iostream>
using namespace std;int main()
{list<int> lt;// 定义初始化为10个2的lt链表lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

2.3.2.rbegin和rend

反向迭代器遍历容器

#include <vector>
#include <list>
#include <iostream>
using namespace std;int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()){cout << *rit << " ";rit++;}cout << endl;return 0;
}

list_314">2.4.list元素的获取访问

2.4.1.front和back

front函数返回对链表第一个元素的引用(用于获取list容器当中的第一个元素),在空容器上调用此函数会有未定义的行为。

back函数用于获取list容器当中的最后一个元素。

#include <iostream>
#include <list>
using namespace std;int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);lt.push_back(6);cout << lt.front() << endl;// 1cout << lt.back() << endl; // 6return 0;
}

list_342">2.5.list的大小控制

2.5.1.size

size用于获取当前容器中的元素个数。

#include <iostream>
#include <list>
using namespace std;
int main()
{list<int> lt(6, 1);cout << lt.size() << endl;return 0;
}

2.5.2.resize

resize的作用:调整容器的大小,使其包含n个元素(n是新容器的大小)。用法如下:

void resize (size_type n, value_type val = value_type());
  1. 如果n小于当前容器的大小(size),则内容将被减少到前n个元素,并删除超出的元素(并销毁它们)。
  2. 如果n大于当前容器的大小,则通过在末尾插入所需的元素来扩展内容,以达到n的大小。如果指定了val,则将新元素初始化为val的副本,否则将其进行值初始化。
  3. resize函数会通过插入或删除元素来改变容器的实际内容。
  4. val值是一个缺省值,如果未指定,就会使用默认构造函数。
  5. 成员类型<font style="color:rgb(42, 43, 46);">value_type</font>是容器中元素的类型,在<font style="color:rgb(42, 43, 46);">list</font>中定义为第一个模板形参(T)的别名。
#include <iostream>
#include <list>
using namespace std;
int main()
{list<int> lt(6, 1);for (auto e : lt){cout << e << " ";}cout << endl;lt.resize(8, 2);// 传了值的情况for (auto e : lt){cout << e << " ";}cout << endl;lt.resize(2);// 没传值,缩容size到3=2for (auto e : lt){cout << e << " ";}cout << endl;return 0;
}

2.5.3.empty

empty的作用:判断容器是否为空(即容器的size是否为0)。用法如下:

bool empty() const;

代码示例:

#include <iostream>
#include <list>
using namespace std;
int main()
{list<int> lt1(10, 2);cout << lt1.empty() << endl;list<int> lt2;cout << lt2.empty() << endl;return 0;
}

2.5.4.clear

clear函数用于判断当前容器是否为空。用法如下:

void clear();

代码示例:

#include <iostream>
#include <list>
using namespace std;int main()
{list<int> lt(5, 1);for (auto e : lt){cout << e << " ";}cout << endl;lt.clear();cout << lt.empty() << endl;return 0;
}

list_459">2.6.list的操作函数

2.6.1.sort

sort函数的作用:对list中的元素进行排序, sort可以将容器中的数据默认排位升序。用法如下:

void sort();
template <class Compare>
void sort(Compare comp);

代码示例:

#include <list>
#include <iostream>
using namespace std;int main()
{list<int> lt;lt.push_back(3);lt.push_back(1);lt.push_back(0);lt.push_back(9);lt.push_back(4);lt.push_back(3);lt.push_back(2);lt.push_back(6);lt.push_back(3);lt.push_back(7);lt.push_back(5);lt.push_back(10);for (auto e : lt){cout << e << " ";}cout << endl;lt.sort();for (auto e : lt){cout << e << " ";}cout << endl;//3 1 0 9 4 3 2 6 3 7 5 10//0 1 2 3 3 3 4 5 6 7 9 10return 0;
}

2.6.2.splice

splice的作用(文档翻译过来):将元素从 “x” 转移到容器当中,并将这些元素插入到特定位置。这样做能够有效地把这些元素插入到容器里,同时从 “x” 中移除它们,进而改变两个容器的大小。此操作既不涉及任何元素的构造,也不涉及任何元素的破坏。无论 “x” 是左值还是右值,也无论元素的值类型是否支持移动构造,这些元素都会被转移。

用法如下:

splice函数用于两个list容器之间的拼接,其有三种拼接方式:

  1. 将整个容器拼接到另一个容器的指定迭代器位置。
  2. 将容器当中的某一个数据拼接到另一个容器的指定迭代器位置。
  3. 将容器指定迭代器区间的数据拼接到另一个容器的指定迭代器位置。
// 将x的所有元素传输到容器中
void splice(iterator position, list& x);
// 只将x指向i的元素传输到容器中
void splice(iterator position, list& x, iterator i);
// 将范围[first,last]从x传输到容器中
void splice(iterator position, list& x, iterator first, iterator last);
// 其中x代表list链表
// position代表容器中插入x的元素的位置
// 指定x中的元素范围的迭代器。将[first,last)范围内的元素转移到position。注意:包括first指向的元素,但是不包括last指向的元素。

代码示例:

#include <iostream>
#include <list>
using namespace std;int main()
{list<int> lt1(4, 1);list<int> lt2(4, 2);lt1.splice(lt1.begin(), lt2);// 在开始位置插入整个list容器for (auto e : lt1){cout << e << " ";}cout << endl;// 此时lt2已经变成空的list容器了for (auto e : lt2){cout << e << " ";}cout << endl;list<int> lt3(4, 3);list<int> lt4(4, 4);lt3.splice(lt3.begin(), lt4, lt4.begin());// 将lt4的第一个位置的数据转移到lt3链表的靠头for (auto e : lt3){cout << e << " ";}cout << endl;for (auto e : lt4){cout << e << " ";}cout << endl;list<int> lt5(4, 2);list<int> lt6(4, 6);lt5.splice(lt5.begin(), lt6, lt6.begin(), lt6.end()); //将容器lt6的指定迭代器区间内的数据拼接到容器lt5的开头for (auto e : lt5){cout << e << " ";}cout << endl; //6 6 6 6 2 2 2 2return 0;
}

2.6.3.remove

从容器中移除值为<font style="color:rgb(42, 43, 46);">val</font>的所有元素。调用这些对象的析构函数,并按移除的元素数量减少容器大小。

remove函数用于删除容器当中特定值的元素。用法如下:

void remove (const value_type& val);

代码示例:

#include <iostream>
#include <list>
using namespace std;int main()
{list<int> lt;lt.push_back(2);lt.push_back(1);lt.push_back(6);lt.push_back(2);lt.push_back(0);lt.push_back(5);lt.push_back(4);for (auto e : lt){cout << e << " ";}cout << endl;lt.remove(2);for (auto e : lt){cout << e << " ";}cout << endl;return 0;
}

2.6.4.remove_if

<font style="color:rgb(42, 43, 46);">remove_if</font>允许使用除相等比较之外的其他条件来确定元素是否被删除。(满足条件就可以使用删除:但是不能是比较像等条件)这将调用这些对象的析构函数,并根据删除的元素数量减少容器大小。用法如下:

template <class Predicate>void remove_if (Predicate pred);

代码示例:

#include <iostream>
#include <list>
using namespace std;bool single_digit(const int& val)
{return val < 10;
}
int main()
{list<int> lt;lt.push_back(10);lt.push_back(4);lt.push_back(7);lt.push_back(18);lt.push_back(2);lt.push_back(5);lt.push_back(9);for (auto e : lt){cout << e << " ";}cout << endl; //10 4 7 18 2 5 9lt.remove_if(single_digit); //删除容器当中值小于10的元素for (auto e : lt){cout << e << " ";}cout << endl; //10 18return 0;
}

2.6.5.unique

unique用于删除容器中连续的重复元素。注意:要想做到真正的驱虫,就需要在对去重前对容器内的元素进行排序。用法如下:

void unique();
template <class BinaryPredicate>void unique (BinaryPredicate binary_pred);

代码示例:

#include <iostream>
#include <list>
using namespace std;
int main()
{list<int> lt;lt.push_back(4);lt.push_back(5);lt.push_back(2);lt.push_back(9);lt.push_back(1);lt.push_back(3);lt.push_back(0);lt.push_back(6);lt.push_back(4);lt.push_back(1);lt.push_back(0);lt.push_back(7);lt.push_back(8);for (auto e : lt){cout << e << " ";}cout << endl;lt.sort();// 先升序排序一下for (auto e : lt){cout << e << " ";}cout << endl;lt.unique();// 删除掉连续的重复元素for (auto e : lt){cout << e << " ";}cout << endl;// 0 1 2 3 4 5 6 7 8 9return 0;
}

2.6.6.merge

merge函数的作用:将一个有序的list容器合并到另一个有序的list容器当中,使得合并后的list容器仍然有序。(类似于归并排序)

  1. 把列表中的各个有序位置上的所有元素转移到一个容器中。这里有一个前提条件,两个容器(原列表和目标容器)都必须已经是有序状态。
  2. 这个操作会有效地使列表 x 变为空,也就是删除了 x 中的所有元素,同时将这些元素插入到目标容器中的有序位置。目标容器的大小会根据传输过来的元素数量进行扩展。
  3. 该操作在执行过程中,不会构造或销毁任何元素。无论 x 是左值还是右值,也无论元素的类型(value_type)是否支持移动构造,元素都会被转移。

用法如下:

void merge(list& x);
template <class Compare>
void merge(list& x, Compare comp);

代码示例:

#include <iostream>
#include <list>
using namespace std;int main()
{list<int> lt1;lt1.push_back(3);lt1.push_back(1);lt1.push_back(8);lt1.push_back(9);lt1.push_back(6);list<int> lt2;lt2.push_back(2);lt2.push_back(10);lt2.push_back(7);lt2.push_back(4);lt1.push_back(5);lt1.sort();lt2.sort();lt1.merge(lt2);for (auto e : lt1){cout << e << " ";}cout << endl;return 0;
}

2.6.7.reverse

reverse函数用于将容器中的元素进行逆置,即反转列表容器中元素的顺序。。用法如下:

void reverse();

代码如下:

#include <iostream>
#include <list>
using namespace std;int main()
{list<int> lt1;lt1.push_back(1);lt1.push_back(3);lt1.push_back(2);lt1.push_back(4);lt1.push_back(7);for (auto e : lt1){cout << e << " ";}cout << endl;lt1.reverse();for (auto e : lt1){cout << e << " ";}cout << endl;return 0;
}

2.6.8.assign

assign函数的作用:用于将新内容分配给容器,替换其当前内容,新内容的赋予方式有两种:

  1. n个值为val的数据分配给容器;
  2. 将所给的迭代器区间当中的内容分配给容器。

其他:

  1. 为被分配的元素所需的任何存储空间,都会使用内部分配器来进行分配。
  2. 在进行调用之前,容器中原本保存的任何元素都将被销毁,然后被新构造的元素所替换(这里不是进行元素赋值操作)。
template <class InputIterator>
void assign(InputIterator first, InputIterator last);
void assign(size_type n, const value_type& val);

代码示例:

#include <iostream>
#include <string>
#include <list>
using namespace std;int main()
{list<char> lt(3, 'a');lt.assign(3, 'b'); //将新内容分配给容器,替换其当前内容for (auto e : lt){cout << e << " ";}cout << endl; //b b bstring s("hello world");lt.assign(s.begin(), s.end()); //将新内容分配给容器,替换其当前内容for (auto e : lt){cout << e << " ";}cout << endl; //h e l l o   w o r l dreturn 0;
}

2.6.9.swap

swap函数用于交换两个容器的内容。


http://www.ppmy.cn/embedded/129479.html

相关文章

基于SpringBoot+Vue+uniapp微信小程序的校园反诈骗微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

python+Mosh网课笔记09标准库

太久没写python代码了&#xff0c;学机器学习重新拾起python&#xff0c;笔记比较简陋。 参考&#xff1a;mosh python网课 目录 一、Files path-文件操作 path-文件夹操作 文件内容读取与编辑 ZIP CSV JSON 一、Files path-文件操作 创建路径的两种方式。一种\\&am…

canvasToTempFilePath: fail canvas is empty. 微信小程序 canvas 报错

如果代码敲累了&#xff0c;就歇一歇。放松一下&#xff0c;问题就会少一些。 问题 在小程序中&#xff0c;使用 canvasToTempFilePath 方法将 canvas 内容保存为临时文件时&#xff0c;有时会遇到 “fail canvas is empty” 的错误。 既然你遇到了这个问题&#xff0c;那么你…

MySQL 数据库的备份与恢复:最佳实践与深度探讨

MySQL 数据库的备份与恢复&#xff1a;最佳实践与深度探讨 在现代应用程序和企业系统中&#xff0c;数据库是其核心组件之一&#xff0c;负责存储和管理大量的关键数据。MySQL 作为一种广泛应用的开源数据库管理系统&#xff0c;支持高性能和可扩展性&#xff0c;被广泛应用于…

LinkedList作者:我虽然开发了LinkedList,但是我更爱用ArrayList

感谢Java面试教程关于LinkedList经验分享 PS冷知识&#xff1a;LinkedList的作者更爱使用ArrayList。 ArrayList 和 LinkedList 是 Java 中两种常见的 List 实现类&#xff0c;它们在底层数据结构、性能特征和使用场景上有显著的区别。 底层数据结构&#xff1a; ArrayList …

RabbitMQ系列学习笔记(四)--消息应答机制

文章目录 一、消息应答详解1、基本概念2、自动应答3、手动应答4、自动重新入队5、手动应答代码6、手动应答演示 二、不公平分发三、预取值机制 本文参考&#xff1a; 尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmq RabbitMQ 详解 Centos7环境安装Erlang、RabbitMQ详细过程…

k8s 外部的 Prometheus 监控 k8s 集群

1. 配置 Kubernetes API 访问 为了让外部的 Prometheus 能够使用 kubernetes_sd_configs 进行服务发现&#xff0c;你需要确保 Prometheus 可以访问 Kubernetes API 服务器&#xff0c;并且具备足够的权限。 1.1 创建 Kubernetes Service Account 并授予权限 首先&#xff0…

家用wifi的ip地址固定吗?换wifi就是换ip地址吗

在探讨家用WiFi的IP地址是否固定&#xff0c;以及换WiFi是否就意味着换IP地址这两个问题时&#xff0c;我们首先需要明确几个关键概念&#xff1a;IP地址、家用WiFi网络、以及它们之间的相互作用。 一、家用WiFi的IP地址固定性 家用WiFi环境中的IP地址通常涉及两类&#xff1a…