全面理解:C++中list(双向链表)容器的基础概念与函数解析

news/2024/11/25 19:54:46/

list容器的基础概念

在 C++ 标准库中,list 是一种双向链表,允许在任何位置进行快速的插入和删除操作。

以下是一些关于 list 的基本信息。

  • 存储:list 是一种双向链表结构,它不像 vector 或 array 那样提供连续的内存存储。

  • 时间复杂度list 在链表的开始、结束或中间位置插入和删除元素的时间复杂度是 O(1)。然而,查找元素的时间复杂度是 O(n)。

  • 空间复杂度:由于链表中每个元素都需要额外存储其前后节点的信息,因此 list 相比于使用连续内存的容器(如 vector 或 array)具有更高的空间复杂度。

  • 迭代器失效当你插入或删除元素时,list 的所有迭代器,包括指向链表开始和结束位置的迭代器,都不会失效。唯一的例外是当你删除一个元素时,指向该元素的迭代器将失效

  • 元素访问list 不支持随机访问。要访问 list 中的元素,你必须从链表的开始(或结束)位置遍历到你要访问的位置。因此,list 不提供 operator[] 函数(下标运算符)

list的函数解析

  • list有各种各样的成员函数,下面我将以函数的功能对这些函数分一下类,然后按照类别,一一介绍这些函数的用处。

构造函数

  • list(): 创建一个空的 list
  • list(n, elem): 创建一个包含 n 个元素的 list,每个元素的值都是 elem
  • list(begin, end): 创建一个包含 [begin, end) 区间元素的 list

以下是使用这些构造函数创建 std::list 的示例:

#include <iostream>
#include <list>
#include <vector>int main() {// 创建一个空的 liststd::list<int> list1;// 创建一个包含 5 个元素的 list,每个元素的值都是 10std::list<int> list2(5, 10);// 从 vector 创建 liststd::vector<int> vec = {1, 2, 3, 4, 5};std::list<int> list3(vec.begin(), vec.end());// 打印 list2for(int i : list2) {std::cout << i << " ";}std::cout << "\n";// 打印 list3for(int i : list3) {std::cout << i << " ";}return 0;
}

元素访问函数

  • front(): 返回首元素
  • back(): 返回尾元素

注意:这里是返回的是链表的元素,而不是指向元素的迭代器或指针

各种迭代器函数

  • begin(): 返回指向首元素的迭代器
  • end(): 返回指向尾元素的下一个位置的迭代器
  • rbegin(): 返回指向尾元素的反向迭代器
  • rend(): 返回指向首元素的前一个位置的反向迭代器

在这里我想详细讲解一下这个迭代器

  • 你可以把list的这个这个迭代器,详细成一个高级的指针。
  • 迭代器是一个对象(指针),假如说list里面的节点元素都是一个个的值了话,这个迭代器就是一个指向这个值的一个指针罢了。我们就可以用解引用符 * 去修改这个值。
  • 假如说迭代器指向的这个对象它是一个类,或者是一个结构体,它有成员变量,那你就可以用箭头符 -> 去操作这个对象的成员变量。你可以把这个对象想象成你自己定义的Listnode,你用箭头符去操作它,hh

判断容器容量函数:

  • empty(): 判断容器是否为空
  • size(): 返回容器中元素的个数
  • max_size(): 返回容器能够容纳的最大元素数量

添加操作

  • insert(position, elem): 在 position 位置前插入一个元素
  • push_back(elem): 在 list 的尾部添加一个元素
  • push_front(elem): 在 list 的头部添加一个元素

删除操作

  • clear(): 删除所有元素
  • erase(position): 删除 position 位置的元素
  • pop_back(): 删除 list 尾部的一个元素
  • pop_front(): 删除 list 头部的一个元素
  • unique(): 删除所有相邻重复元素
  • remove_if(predicate): 删除满足条件 predicate 的所有元素
  • remove(elem): 删除所有值为 elem 的元素

修改容器大小的函数

  • resize(size, elem): 改变容器的大小,如果需要添加元素,则元素值为 elem

具体讲解一下splice()这个函数

splice() 是list 的一个非常有用的成员函数,它可以高效地将元素从一个列表移到另一个列表,或者从列表的一个位置移动到另一个位置因为它是重新链接节点指针,不会导致元素内容的复制或移动,所以速度非常快。它一共有三种重载版本。

三种重载版本如下:

  • void splice (const_iterator position, list& x);

    • 将 x 中的所有元素移到当前列表的 position 位置。 x 变为空。
  • void splice (const_iterator position, list& x, const_iterator i);

    • 将 x 中的元素 i 移到当前列表的 position 位置。 i 在 x 中的元素被移除。
  • void splice (const_iterator position, list& x, const_iterator first, const_iterator last);

    • 将 x 中的 [first, last) 区间的元素移到当前列表的 position 位置。 这个区间在 x 中的元素被移除。

    • 注意:position 和 x 可以指向同一个列表,但 position 不能在 [first, last) 区间内。

下面是使用 splice() 的例子:

#include <iostream>
#include <list>int main() {std::list<int> list1 = {1, 2, 3};std::list<int> list2 = {4, 5, 6};// move all elements of list2 to list1list1.splice(list1.end(), list2);std::cout << "list1: ";for (int num : list1) {std::cout << num << " ";}std::cout << "\n";std::cout << "list2: ";for (int num : list2) {std::cout << num << " ";}std::cout << "\n";// move back one element from list1 to list2list2.splice(list2.begin(), list1, --list1.end());std::cout << "list1: ";for (int num : list1) {std::cout << num << " ";}std::cout << "\n";std::cout << "list2: ";for (int num : list2) {std::cout << num << " ";}std::cout << "\n";return 0;
}

在这个例子中,我们首先创建了两个列表。然后,我们将 list2 中的所有元素移动到 list1 的尾部。接着,我们将 list1 的最后一个元素移动到 list2 的头部。每次操作后,我们都打印出两个列表的内容。

交换元素的函数

  • swap(list): 交换两个 list

反转链表函数

  • reverse(): 反转 list

对链表进行排序的函数

  • sort(): 排序 list

这是一些使用 list 的示例:

#include <iostream>
#include <list>int main() {std::list<int> numbers;// push elementsnumbers.push_back(5);numbers.push_back(10);numbers.push_front(1);// iterate through the listfor(std::list<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {std::cout << *it << ' ';}std::cout << '\n';// remove an elementnumbers.remove(1);for(auto &num : numbers) {std::cout << num << ' ';}std::cout << '\n';// sort the listnumbers.sort();for(auto &num : numbers) {std::cout << num << ' ';}std::cout << '\n';return 0;
}

这段代码首先创建了一个空的 list,然后在尾部和头部添加了一些元素。然后它通过迭代器遍历 list 并打印每个元素。然后它删除一个元素,并再次打印 list。最后,它对 list 进行排序,并打印排序后的 list。

总结

  • 在C++标准库中,list是一种双向链表,允许在任何位置进行快速的插入和删除操作。list在任何位置插入和删除元素都有相对稳定的性能,而不是依赖于元素在容器中的位置。

  • 我们讨论了list的多种构造函数,包括默认构造函数、初始化列表构造函数、以及从其他容器复制元素的构造函数。

  • 我们也介绍了 splice() 函数,这是一个非常有用的成员函数,它可以高效地将元素从一个列表移到另一个列表。splice()有三种重载版本,它们都不会导致元素内容的复制或移动,而是重新链接节点指针,因此速度非常快。

最后,我们讨论了一些其他的std::list成员函数,包括元素访问、迭代器、容量查询、列表修改和操作等。

最后的最后,如果你觉得我的这篇文章写的不错的话,请给我一个赞与收藏,关注我,我会继续给大家带来更多更优质的干货内容


http://www.ppmy.cn/news/108582.html

相关文章

IIC总线协议的死锁问题

目录 1. IIC的特性 2. IIC死锁问题分析 3. 常见的IIC死锁问题解决方法 1. IIC的特性 IIC协议是一个允许一主多从通信的协议&#xff0c;只能用于短距离通信&#xff0c;并且只需要两根信号线来交换信息。 IIC的两根信号是SCL和SDA&#xff0c;SCL是时钟信号线&#xff0c;S…

Java之路:构建坚实基础,系统学习Java技术的终极指南

无论是初学者还是有经验的专业人士&#xff0c;在学习一门新的IT技术时&#xff0c;都需要采取一种系统性的学习方法。作为一名Java技术er&#xff0c;下面我将介绍我是如何系统的学习Java技术的。 一、Java技术介绍 Java是一种广泛应用于软件开发的高级编程语言&#xff0c;…

docker的基本相关知识和操作

镜像相关操作命令&#xff1a; 访问DockerHub搜索镜像&#xff0c;https://hub.docker.com/ 查看本地镜像&#xff1a;docker images 搜索镜像 docker search redis &#xff08;搜索redis&#xff09; 拉取镜像&#xff1a;docker pull redis &#xff08;默认版本&#x…

【学习日记2023.5.30】之 订单处理 订单状态定时处理_来单提醒_用户催单

文章目录 10. 订单处理10.1 Spring Task10.1.1 介绍10.1.2 cron表达式10.1.3 入门案例10.1.3.1 Spring Task使用步骤10.1.3.2 代码开发10.1.3.3 功能测试 10.1.4提交代码 10.2 订单状态定时处理10.2.1 需求分析10.2.2 代码开发10.2.3 功能测试 10.3 WebSocket10.3.1 介绍10.3.2…

SQl Server 2008 知识点概括【数据库】

1. 第一章 数据库概述 什么是数据库&#xff1f; 数据库是采用计算机技术统一管理的相关数据的集合&#xff0c;数据库能为各种用户共享&#xff0c;具有冗余度最小、数据之间联系密切、有较高数据独立性等特点。Microsoft SQL Server 系统的体系结构 Microsoft SQL Server 20…

gitlab占用内存太大了如何解决?

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号雄雄的小课堂 现在是&#xff1a;2023年5月30日16:58:15 最近在家里自己搞了个服务器&#xff0c;因为这台机器都不用了&#xff0c;从朋友那拿过来&#xff0c;就当服务器用了&#xff0c;看了下&#xff0c;比云服…

UEFI开发环境搭建(Windows)

重拾UEFI学习。 第一步是搭建开发环境&#xff0c;记录如下&#xff1a; 1. 安装开发工具 Visual Studio 2017 python/ASL/NASM 安装到如下目录&#xff1a; c:\Python310 c:\ASL c:\NASM 更新系统变量Path: 新建系统变量PYTHON_HOME 下载EDK2 创建工作目录&#xff…

C++ > Cmake

目录 编译器 多文件编译与链接 Makefile构建系统 编译器 厂商 C C GNU gcc g main.cpp #include <cstdio>int main() {printf("Hello, world!\n");return 0; }编译器, 是一个根据源代码生成机器码的程序 g main.cpp -o a.out调用编译器程序g, 读…