深入探索 C++ STL 中的 List 容器

深入探索 C++ STL 中的 std::list 容器

在 C++ 标准模板库(STL)中,std::list 是一种非常灵活且功能强大的容器。它基于双向循环链表实现,提供了高效的插入和删除操作,同时支持双向迭代器。本文将通过一系列示例代码,深入探讨 std::list 的构造、操作、排序以及与其他容器的比较,帮助读者更好地理解和使用这一强大的工具。

1. std::list 的构造方式

std::list 提供了多种构造方式,可以根据不同的需求灵活创建链表。以下是几种常见的构造方法:

1.1 默认构造

cpp复制

list<int> l1;

这种方式会创建一个空的链表,不包含任何元素。

1.2 指定范围构造

cpp复制

list<int> l2(l1.begin(), l1.end());

这种方式会根据给定的迭代器范围构造链表,l2 将包含 l1 中的所有元素。

1.3 指定元素构造

cpp复制

list<int> l3(5, 8);

这种方式会创建一个包含 5 个值为 8 的元素的链表。

1.4 拷贝构造

cpp复制

list<int> l4(l3);

这种方式会创建一个与 l3 完全相同的链表。

2. std::list 的基本操作

std::list 提供了一系列操作接口,用于插入、删除、访问元素等。以下是一些常用操作的示例:

2.1 插入操作

cpp复制

list<int> l;
l.push_back(1); // 在链表尾部插入元素
l.push_front(2); // 在链表头部插入元素

此外,还可以使用迭代器指定插入位置:

cpp复制

list<int>::iterator it = l.begin();
l.insert(it, 3); // 在迭代器指向的位置插入元素

2.2 删除操作

cpp复制

l.pop_back(); // 删除链表尾部的元素
l.pop_front(); // 删除链表头部的元素

使用迭代器删除指定元素:

cpp复制

l.erase(it); // 删除迭代器指向的元素

还可以删除指定范围内的元素:

cpp复制

l.erase(l.begin(), --l.end());

2.3 清空链表

cpp复制

l.clear();

2.4 元素访问

std::list 不支持随机访问,因此不能使用 [].at() 方法。但可以通过迭代器访问元素:

cpp复制

list<int>::iterator it = l.begin();
cout << *it << endl; // 访问迭代器指向的元素

3. std::list 的大小操作

std::list 提供了 size()empty() 方法,用于获取链表的大小和判断是否为空:

cpp复制

cout << l.size() << endl; // 获取链表大小
cout << l.empty() << endl; // 判断链表是否为空

此外,还可以通过 resize() 方法调整链表的大小:

cpp复制

l.resize(8); // 将链表大小调整为 8
l.resize(2); // 将链表大小调整为 2

4. std::list 的排序与反转

std::list 提供了 sort()reverse() 方法,用于对链表进行排序和反转:

4.1 反转链表

cpp复制

l.reverse();

4.2 排序

std::listsort() 方法默认按照从小到大的顺序对元素进行排序:

cpp复制

l.sort();

如果需要自定义排序规则,可以传入一个比较函数:

cpp复制

bool my_comp(int a, int b) {
    return a > b;
}
l.sort(my_comp); // 按照自定义规则排序

5. std::list 的高级用法

5.1 自定义数据类型排序

std::list 可以存储自定义数据类型,并通过自定义比较函数进行排序。例如,定义一个 person 类,并按照年龄升序、身高降序排序:

cpp复制

class person {
public:
    int m_id;
    int m_age;
    int m_height;
    person(int id, int age, int height) : m_id(id), m_age(age), m_height(height) {}
};

bool my_comp(person p1, person p2) {
    if (p1.m_age == p2.m_age) {
        return p1.m_height > p2.m_height;
    } else {
        return p1.m_age < p2.m_age;
    }
}

list<person> p;
p.push_back(person(1001, 22, 159));
p.push_back(person(1002, 18, 168));
p.push_back(person(1003, 22, 179));
p.push_back(person(1004, 19, 181));

p.sort(my_comp);

5.2 赋值与交换

std::list 提供了多种赋值和交换操作:

cpp复制

list<int> l1;
l1.push_back(1);
l1.push_back(2);

list<int> l2 = l1; // 赋值操作
l1.swap(l2); // 交换两个链表的内容

6. std::list 与其他容器的比较

std::list 是一种基于双向循环链表的容器,与其他容器(如 std::vectorstd::deque)相比,具有以下特点:

  • 插入和删除效率高std::list 在链表头部、尾部或中间插入和删除元素的时间复杂度为 O(1),而 std::vectorstd::deque 在中间插入和删除元素时可能需要移动大量元素。

  • 不支持随机访问std::list 不支持随机访问,因此不能使用 [].at() 方法。如果需要随机访问,建议使用 std::vectorstd::deque

  • 内存分配灵活std::list 的内存分配是动态的,每个元素单独分配内存,因此内存消耗相对较大。而 std::vectorstd::deque 的内存分配是连续的,内存利用率更高。

7. 总结

std::list 是 C++ STL 中一个非常强大的容器,适用于需要频繁插入和删除元素的场景。通过本文的介绍,读者可以更好地理解和使用 std::list,并根据实际需求选择合适的容器类型。希望本文对您有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值