STL容器——list类

一、list是什么

list官方文档

在数组中,数据在逻辑空间和物理空间上都是连续的。

而链表中的数据在逻辑上时连续的在物理空间上不是连续的。所以可以更好的利用空间,但是不能随机访问。

访问时只能访问下一个,就是单向链表 ,可以访问上一个和下一个,就是双向链表

STL的list就是:C 语言里的双向链表,被 C++ 封装好了,你不用自己写结构体、不用自己管理指针,直接拿来用就行。


二、list的特点

1. 任意位置插入 / 删除元素效率极高(O (1))

vector在插入或删除元素时,需要移动后面所有元素,效率是 O(n);

list 是双向链表,只需要修改节点的指针指向,不移动任何元素,无论在头部、中间、尾部操作,时间复杂度都是固定的 O(1)。

2. 高效的链表拼接(splice)

list 提供 splice() 函数,可以把另一个 list 的节点直接拼接到当前 list

时间复杂度 O(1),不拷贝、不移动任何元素,仅修改指针;

vector 做类似操作必须拷贝数据,效率较慢。

3. 内存分配灵活,无空间浪费

vector 是连续内存,会预分配多余空间,存在内存浪费;

list 每个元素独立分配节点内存,用多少分配多少,没有冗余空间;

不会因为扩容导致大量内存拷贝。

4.不支持随机访问

不能用 \[\] 或 .at() 直接访问第 k 个元素,只能从头 / 尾遍历,查找慢(O (n));

5.内存占用大

每个节点都要存储前后指针,内存占用比 vector 高;

6.遍历速度略慢

节点不连续,遍历速度慢于 vector。


三、list的使用

3.1 list的初始化

名称 使用示例 功能说明
default(默认构造) list<int> lst1; 创建一个空链表,无任何元素
fill(填充构造) list<int> lst2(5, 10); 5 个元素,每个都是 10
range(迭代器初始化) list<int> lst4(src.begin() + 1, src.end() - 1) 用 [first, last) 区间元素构造
copy(拷贝构造) list<int> lst5(lst2); 复制 lst2

这里和之前学习的容器很统一,因为他们都是顺序容器。

使用示例

在使用时要使用"#include<list>"头文件

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;

void print(const list<int>& lst) {
    for (int x : lst) cout << x << " ";
    cout << endl;
}

int main() {
    // 1. 默认构造:空链表
    list<int> lst1;
    cout << "1. 默认构造: ";
    print(lst1);

    // 2. 填充构造:5个10
    list<int> lst2(5, 10);
    cout << "2. 填充构造: ";
    print(lst2);

    // 3. 迭代器区间构造
    list<int> src = {1,2,3,4,5};
    list<int> lst3(src.begin(), src.end());
    cout << "3. 迭代器构造: ";
    print(lst3);

    // 4. 拷贝构造
    list<int> lst4(lst2);
    cout << "4. 拷贝构造: ";
    print(lst4);

    return 0;
}

3.2 list类对象的容量操作

| 名称 | 使用示例 | 功能说明 |
| size | lst.size() | 获取list中实际存储的元素个数 |

empty lst.empty() 检测list是否为空,为空返回true,否则返回false

使用示例

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;

int main()
{
    list<int> v1;

    cout << "是否为空:" << boolalpha << v1.empty() << endl;
    cout << "元素个数:" << v1.size() << endl;

    v1.push_back(1);
    v1.push_back(2);

    cout << "是否为空:" << boolalpha << v1.empty() << endl;
    cout << "元素个数:" << v1.size() << endl;

    return 0;
}

3.3 list类对象的访问及遍历操作

名称 使用示例 功能说明
begin() end() s.begin() s.end () begin() 获取指向第一个元素的迭代器;end() 获取指向最后一个元素下一个位置的迭代器
rbegin() rend() s.rbegin () s.rend () rbegin() 获取指向最后一个元素的反向迭代器;rend() 获取指向第一个元素前一个位置的反向迭代器
范围 for(C++11) for (char ch : s) {cout << ch;} 更简洁的遍历方式,底层等价于迭代器遍历
front() lst.front() 返回 list 第一个元素的引用
back() lst.back() 返回 list 最后一个元素的引用

这里少了\[\]访问。

使用示例

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst = {10, 20, 30};

    // 1. begin() + end() 正向遍历
    cout << "正向遍历:";
    for (auto it = lst.begin(); it != lst.end(); ++it)
        cout << *it << " ";
    cout << endl;

    // 2. rbegin() + rend() 反向遍历
    cout << "反向遍历:";
    for (auto it = lst.rbegin(); it != lst.rend(); ++it)
        cout << *it << " ";
    cout << endl;

    // 3. 范围for(最简单)
    cout << "范围for:";
    for (int x : lst)
        cout << x << " ";
    cout << endl;

    // 4. front() 第一个元素
    cout << "第一个元素:" << lst.front() << endl;

    // 5. back() 最后一个元素
    cout << "最后一个元素:" << lst.back() << endl;

    return 0;
}

3.4 list类对象的修改操作

| 名称 | 使用示例 | 功能说明 |
| push_front(val) | | 在 list 首元素前插入值为 val 的元素 |
| pop_front() | | 删除 list 中第一个元素 |
| push_back(val) | | 在 list 尾部插入值为 val 的元素 |
| pop_back() | | 删除 list 中最后一个元素 |
| insert(pos, val) | | 在迭代器 pos 指向的位置前插入值为 val 的元素 |
| erase(pos) | | 删除迭代器 pos 指向的元素 |
| swap(other) | | 交换两个 list 的内容 |

clear() 清空 list 中的所有有效元素

使用示例

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> l;

    // 1. 头尾添加
    l.push_back(10);      // 容器:[10]
    l.push_front(20);     // 容器:[20, 10]
    l.push_back(30);      // 容器:[20, 10, 30]

    // 2. insert 插入
    auto it = l.begin();
    l.insert(++it, 50);   // 在20后面插入50 → [20, 50, 10, 30]

    // 3. 删除头尾
    l.pop_front();        // 删除第一个20 → [50, 10, 30]
    l.pop_back();         // 删除最后30 → [50, 10]

    // 4. erase 删除指定位置
    l.erase(l.begin());   // 删除第一个50 → [10]

    // 5. clear 清空
    l.clear();            // 清空 → 元素个数:0

    // 6. swap 交换两个list
    list<int> l1 = {1,2};
    list<int> l2 = {3,4};
    l1.swap(l2);          // l1变成[3,4],l2变成[1,2]

    return 0;
}
相关推荐
love_muming4 分钟前
从 ArrayList 到 LinkedList:Java 集合中数组与链表的深度对比
java·数据结构·链表
牟师傅敲代码6 分钟前
第2章:底层时间驱动机制
c++
并不喜欢吃鱼21 分钟前
从零开始 C++------ 十四【C++ 数据结构】unordered_map/unordered_set 全解析:从使用到底层模拟实现
开发语言·数据结构·c++
小欣加油29 分钟前
leetcode3633 最早完成陆地和水上游乐设施的时间I
数据结构·c++·算法·leetcode
啦啦啦啦啦zzzz31 分钟前
数据结构:二叉排序树(递归与非递归函数的全部实现)
数据结构·c++·二叉排序树
£suPerpanda1 小时前
AtCoder Beginner Contest 453
c++·算法
郝学胜-神的一滴1 小时前
Qt 高级开发 022:栅格布局深度实战
开发语言·c++·qt·软件构建·用户界面
basketball6161 小时前
设计模式入门:3. 装饰器模式详解 C++实现
c++·设计模式·装饰器模式
程序大视界1 小时前
【C++ 从基础到项目实战】C++(三):函数进阶——重载、回调、递归与默认参数
开发语言·c++·cpp
西梅汁1 小时前
C++ 线程间通信(二)
c++