想象一位魔术师有一条神奇的链条:
这就是C++标准库中的**list
**——它用双向链表的结构,赋予你高效增删元素的能力,告别数组搬移数据的笨重操作!
std::list
是C++标准模板库(STL)提供的双向链表容器。
特性 | vector | list |
---|---|---|
内存布局 | 连续内存,缓存友好 | 非连续内存,指针链接 |
随机访问 | O(1) | O(n) |
中间插入删除 | O(n)(需搬移元素) | O(1) |
迭代器类型 | 随机访问迭代器 | 双向迭代器 |
#include
using namespace std;
list<int> nums1; // 空链表
list<string> names(3, "Alice"); // 3个"Alice"
list<char> letters{'a', 'b', 'c'}; // 初始化列表(C++11)
list<double> values2(values1); // 拷贝构造
nums1.push_back(10); // 末尾插入
nums1.push_front(0); // 头部插入
auto it = nums1.begin();
advance(it, 2); // 移动迭代器到第3个位置
nums1.insert(it, 99); // 在指定位置插入
nums1.emplace_back(20); // C++11,避免临时对象拷贝
nums1.pop_back(); // 删除末尾元素
nums1.pop_front(); // 删除头部元素
nums1.erase(it); // 删除迭代器指向的元素
nums1.remove(99); // 删除所有值为99的元素
nums1.clear(); // 清空链表
cout << nums1.front(); // 第一个元素
cout << nums1.back(); // 最后一个元素
// 注意:list没有[]和at()方法!
// 传统迭代器
for (auto it = letters.begin(); it != letters.end(); ++it) {
cout << *it << " ";
}
// 范围for循环(C++11)
for (char c : letters) {
cout << c << " ";
}
// 反向遍历
for (auto rit = letters.rbegin(); rit != letters.rend(); ++rit) {
cout << *rit << " ";
}
auto it = find(letters.begin(), letters.end(), 'b');
if (it != letters.end()) {
cout << "找到b,位置:" << distance(letters.begin(), it);
}
list<int> list1{1, 2, 3};
list<int> list2{4, 5, 6};
list1.splice(list1.end(), list2); // 将list2全部元素移动到list1末尾
// list1变为{1,2,3,4,5,6},list2为空
list<int> nums{3, 1, 4, 1, 5};
nums.sort(); // 升序排序:{1, 1, 3, 4, 5}
nums.unique(); // 去重:{1, 3, 4, 5}
nums.reverse(); // 反转:{5, 4, 3, 1}
list<int> listA{1, 3, 5};
list<int> listB{2, 4, 6};
listA.merge(listB); // listA变为{1,2,3,4,5,6},listB为空
// 注意:合并前两个链表必须已排序!
// 按降序排序
nums.sort([](int a, int b) { return a > b; });
auto it = nums.begin();
++it;
nums.erase(it); // 此时it已失效,不可再使用
// 低效操作:频繁访问中间元素
for (int i = 0; i < nums.size(); i++) {
// 需要从头遍历到第i个位置!
auto it = nums.begin();
advance(it, i);
cout << *it;
}
每个元素需要额外存储前后指针(每个指针通常4/8字节),小对象存储效率低于vector。
利用list快速移动元素的特性:
list<pair<int, string>> cache;
unordered_map<int, list<pair<int, string>>::iterator> map;
void access(int key) {
auto it = map[key];
cache.splice(cache.begin(), cache, it); // 移动到头部
}
list<int> listX{1, 3, 5};
list<int> listY{2, 4, 6};
listX.merge(listY);
// listX变为{1,2,3,4,5,6}
std::list
以其高效的增删能力和稳定的迭代器,成为处理动态序列的利器。
当你需要频繁修改数据序列时,不妨让list
成为你的首选容器——它不仅是链表,更是高效数据操作的秘密武器!
(完)
希望这篇博客能帮助读者掌握C++ list的核心技巧!如果需要调整示例或补充细节,请随时告诉我~