介绍
序列容器之list是一种在C++标准模板库(STL)中广泛使用的数据结构,它基于双向链表实现,提供了在常数时间内进行任意位置插入和删除操作的能力。
定义:list是一种序列容器,可以存储具有相同类型的元素序列。
底层实现:list的底层是通过双向链表实现的,每个节点包含数据部分和两个指针,分别指向前一个节点和后一个节点。
双向迭代:list支持前后双向迭代,即可以从前往后遍历,也可以从后往前遍历。
常数时间插入和删除:在list的任意位置插入或删除元素,都可以在常数时间内完成,因为只需要改变相关节点的指针即可,无需移动其他元素。
不支持随机访问:由于list是基于链表实现的,因此不支持像数组或vector那样的随机访问(即不能使用下标直接访问元素),访问元素的时间复杂度为O(n)。
空间分配不连续:与vector不同,list的内存分配是不连续的,每个节点都是独立分配的,因此不需要担心扩容问题。
创建和初始化
#include <iostream>
#include <deque>
int main() {
// 创建一个空的deque
std::deque<int> dq;
// 使用初始值创建deque
std::deque<int> dq_with_size(5); // 创建一个包含5个元素的deque,元素值为默认值0
std::deque<int> dq_with_values(5, 10); // 创建一个包含5个元素的deque,元素值为10
// 使用列表初始化deque
std::deque<int> dq_with_list = {1, 2, 3, 4, 5};
return 0;
}
添加元素
#include <iostream>
#include <deque>
int main() {
std::deque<int> dq;
// 在deque的末尾添加元素
dq.push_back(1);
dq.push_back(2);
dq.push_back(3);
// 在deque的开头添加元素
dq.push_front(0);
// 插入元素到指定位置
auto it = dq.begin();
std::advance(it, 2);
dq.insert(it, 4); // 在第三个位置插入4
for (int val : dq) {
std::cout << val << " "; // 输出: 0 1 4 2 3
}
std::cout << std::endl;
return 0;
}
访问元素
#include <iostream>
#include <deque>
int main() {
std::deque<int> dq = {1, 2, 3, 4, 5};
// 使用下标访问元素
std::cout << dq[0] << std::endl; // 输出: 1
// 使用at()方法访问元素
std::cout << dq.at(1) << std::endl; // 输出: 2
// 访问第一个和最后一个元素
std::cout << dq.front() << std::endl; // 输出: 1
std::cout << dq.back() << std::endl; // 输出: 5
return 0;
}
遍历元素
#include <iostream>
#include <deque>
int main() {
std::deque<int> dq = {1, 2, 3, 4, 5};
// 使用范围for循环遍历
for (int val : dq) {
std::cout << val << " ";
}
std::cout << std::endl;
// 使用传统for循环遍历
for (size_t i = 0; i < dq.size(); ++i) {
std::cout << dq[i] << " ";
}
std::cout << std::endl;
// 使用迭代器遍历
for (auto it = dq.begin(); it != dq.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
删除元素
#include <iostream>
#include <deque>
int main() {
std::deque<int> dq = {1, 2, 3, 4, 5};
// 删除第一个元素
dq.pop_front();
// 删除最后一个元素
dq.pop_back();
// 删除指定位置的元素
auto it = dq.begin();
std::advance(it, 1); // 指向第二个元素
dq.erase(it);
// 删除指定范围的元素
auto it1 = dq.begin();
auto it2 = dq.begin();
std::advance(it2, 2);
dq.erase(it1, it2); // 删除前两个元素
for (int val : dq) {
std::cout << val << " "; // 可能输出: 3 4 5
}
std::cout << std::endl;
return 0;
}
其他常用操作
#include <iostream>
#include <deque>
int main() {
std::deque<int> dq = {1, 2, 3, 4, 5};
// 获取deque的大小
std::cout << "Size: " << dq.size() << std::endl; // 输出: Size: 5
// 检查deque是否为空
std::cout << "Is empty: " << std::boolalpha << dq.empty() << std::endl; // 输出: Is empty: false
// 改变deque的大小
dq.resize(3); // 现在dq包含3个元素
// 清空deque
dq.clear(); // 现在dq为空
for (int val : dq) {
std::cout << val << " "; // 不会输出任何东西,因为dq为空
}
std::cout << std::endl;
return 0;
}
总结
list是一种基于双向链表实现的序列容器,它提供了在常数时间内进行任意位置插入和删除操作的能力,但不支持随机访问。list的灵活性和高效性使得它在处理需要频繁插入和删除操作的场景时非常有用。