文章目录
- [deque 基本概念](#deque 基本概念)
- [deque 构造函数](#deque 构造函数)
- deque赋值操作
- [deque 大小操作](#deque 大小操作)
- [deque 插入和删除](#deque 插入和删除)
- [deque 数据存取](#deque 数据存取)
- [deque 排序](#deque 排序)
仓库链接
本仓库提供STL相关每一篇文章的完整可运行示例代码。
bash
git clone https://github.com/MaikieMaiky/cpp_STL.git
deque 基本概念
Double-ended queue (Qw) 双端队列
deque读音与deck一致
功能:
- 双端数组,可对头部/尾部执行插入删除动作
deque与vector区别:
- vector头插效率低
- deque头插效率高
- vector访问更快
cpp
front() back()
----------------------------------
push_front() -----> push_back()
1 2 _ 3 4 5
pop_front() ^ ^ ^ ^ pop_back()
--|----------|-------------|------|---
v.rend() v.begin() insert() v.begin() v.end()
内部工作原理:
- deque内部有一个中控器,维护每段缓冲区的内容,缓冲区放真实数据
- 中控器维护的是每个缓冲区的地址,使得使用时看起来像一片连续的内存空间
- 每个缓冲区都是分开的,需要通过地址去查找,自然访问的速度没有连续的vector快
cpp
(中控器)
| | --->[ ele ele ele] (头插方便)
|0x01|--|
|0x02|----->[ele ele ele ele ele ele]
|0x02|--|
| | --->[ele ele ele ] (尾插方便)
| |
(二次寻址,访问元素自然慢)
- deque容器的迭代器也支持随机访问
- deque的成员函数和vector基本一样,使用也基本一样,了解一下即可
deque 构造函数
打印容器使用const限制已读
迭代器使用const_iterater
原型:
-
deque<T> deq;// 默认构造形式 -
deque(beg, end);// 构造函数将[beg, end)区间中的元素拷贝给本身。(迭代器区间) -
deque(n, elem);// 构造函数将n个elem拷贝给本身。 -
deque(const deque &deq);// 拷贝构造函数 -
示例
cpp// deque的构造函数 /** * deque<T> deq; // 默认构造形式 * deque(beg, end); // 构造函数将[beg, end)区间中的元素拷贝给本身。(迭代器区间) * deque(n, elem); // 构造函数将n个elem拷贝给本身。 * deque(const deque &deq); // 拷贝构造函数 */ #include <iostream> #include <deque> using namespace std; // 使用const deque保证只读不修改 void print_deque(const deque<int>& d) { // 因为只读不修改,因此需要使用const_iterator for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { // 1. 默认构造 deque<int> d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } cout << "d1 = "; print_deque(d1); // 2. 迭代器区间拷贝 deque<int> d2(d1.begin(), d1.end()); cout << "d2 = "; print_deque(d2); // 3. 将n个elem拷贝给本身。 deque<int> d3(10, 66); cout << "d3 = "; print_deque(d3); // 4. 拷贝构造 deque<int> d4(d3); cout << "d4 = "; print_deque(d4); } int main() { test0(); return 0; } -
这里新增一个知识点,打印deque只需要读而不用改,因此可以使用const来约束输入的deque保证只读,并且配合使用const_iterator来实现
deque赋值操作
原型:
-
deque& operator=(const deque &deq);// 重载=操作符 -
assign(beg, end);// 将[beg, end)区间中的数据拷贝赋值给本身(迭代器区间) -
assign(n, elem);// 将n个elem拷贝赋值给本身 -
示例
cpp// deque的赋值操作 /** * deque& operator=(const deque &deq); // 重载=操作符 * assign(beg, end); // 将[beg, end)区间中的数据拷贝赋值给本身(迭代器区间) * assign(n, elem); // 将n个elem拷贝赋值给本身 */ #include <iostream> #include <deque> using namespace std; void print_deque(const deque<int>& d) { for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { deque<int> d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } cout << "d1 = "; print_deque(d1); // 1. 重载=操作符 deque<int> d2; d2 = d1; cout << "d2 = "; print_deque(d2); // 2. 将[beg, end)区间中的数据拷贝赋值给本身(迭代器区间) deque<int> d3; d3.assign(d1.begin(), d1.end()); cout << "d3 = "; print_deque(d3); // 3. 将n个elem拷贝赋值给本身 deque<int> d4; d4.assign(10, 66); cout << "d4 = "; print_deque(d4); } int main() { test0(); return 0; }
deque 大小操作
deque和vector有一点不同:无capacity,只有size,deque可以无限开辟缓冲区,中控器加地址即可,不需要提前分配大块
原型:
-
size();// 返回容器中元素的个数 -
empty();// 判断容器是否为空 -
resize(num);// 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 -
resize(num, elem);// 重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 -
示例
cpp// deque的大小操作 /** * size(); // 返回容器中元素的个数 * empty(); // 判断容器是否为空 * resize(num); // 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 * resize(num, elem); // 重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 */ #include <iostream> #include <deque> using namespace std; void print_deque(const deque<int>& d) { for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { deque<int> d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } cout << "d1 = "; print_deque(d1); // 1. 返回容器中元素的个数 cout << "d1.size() = " << d1.size() << endl; // 2. 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 d1.resize(15); cout << "d1 = "; print_deque(d1); cout << "d1.size() = " << d1.size() << endl; // 3. 重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 d1.resize(20, 22); cout << "d1 = "; print_deque(d1); cout << "d1.size() = " << d1.size() << endl; // 4. 判断容器是否为空 if (d1.empty()) { cout << "d1 is empty" << endl; } else { cout << "d1 is not empty" << endl; } } int main() { test0(); return 0; }
deque 插入和删除
原型:
两端插入/删除
push_back(elem);// 在容器尾部添加一个数据push_front(elem);// 在容器头部插入一个数据pop_back();// 删除容器最后一个数据pop_front();// 删除容器第一个数据
指定位置(pos处需要输入迭代器)
-
insert(pos, elem);// 在pos位置插入一个elem元素的拷贝,返回新数据的位置。 -
insert(pos, n, elem);// 在pos位置插入n个elem数据,无返回值。 -
insert(pos, beg, end);// 在pos位置插入[beg, end)区间的数据,无返回值。 -
erase(pos);// 删除pos位置的数据,返回下一个数据的位置。 -
erase(beg, end);// 删除[beg, end)区间的数据,返回下一个数据的位置。 -
clear();// 清空容器中的所有数据 -
示例
cpp// deque的插入和删除 /** * 两端插入/删除 * push_back(elem); // 在容器尾部添加一个数据 * push_front(elem); // 在容器头部插入一个数据 * pop_back(); // 删除容器最后一个数据 * pop_front(); // 删除容器第一个数据 * * 指定位置操作(pos处需要输入迭代器) * insert(pos, elem); // 在pos位置插入一个elem元素的拷贝,返回新数据的位置。 * insert(pos, n, elem); // 在pos位置插入n个elem数据,无返回值。 * insert(pos, beg, end); // 在pos位置插入[beg, end)区间的数据,无返回值。 * erase(pos); // 删除pos位置的数据,返回下一个数据的位置。 * erase(beg, end); // 删除[beg, end)区间的数据,返回下一个数据的位置。 * clear(); // 清空容器中的所有数据 */ #include <iostream> #include <deque> using namespace std; void print_deque(const deque<int>& d) { for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { deque<int> d1; // 尾插 d1.push_back(10); d1.push_back(20); d1.push_back(30); // 头插 d1.push_front(100); d1.push_front(200); d1.push_front(300); cout << "d1 = "; print_deque(d1); // 尾删 d1.pop_back(); // 头删 d1.pop_front(); cout << "d1 = "; print_deque(d1); // 指定位置插入 d1.insert(d1.begin() + 1, 1000); cout << "d1 = "; print_deque(d1); // 指定位置插入n个elem数据 d1.insert(d1.end() - 1, 2, 2000); cout << "d1 = "; print_deque(d1); // 指定位置插入[beg, end)区间的数据 deque<int> d2; d2.push_back(1); d2.push_back(2); d2.push_back(3); d1.insert(d1.begin() + 1, d2.begin(), d2.end()); cout << "d1 = "; print_deque(d1); // 指定位置删除 d1.erase(d1.begin()); cout << "d1 = "; print_deque(d1); // 删除指定位置的元素 d1.erase(d1.begin() + 1); cout << "d1 = "; print_deque(d1); // 删除指定位置的元素 d1.erase(d1.begin() + 1, d1.begin() + 3); cout << "d1 = "; print_deque(d1); // 清空容器中的所有数据 d1.clear(); cout << "d1 = "; print_deque(d1); } int main() { test0(); return 0; }
deque 数据存取
原型:
-
at(idx);// 返回索引idx所指的数据 -
operator[];// 返回索引idx所指的数据 -
front();// 返回首元素 -
back();// 返回尾元素 -
示例
cpp// deque的数据存取 /** * at(idx); // 返回索引idx所指的数据 * operator[]; // 返回索引idx所指的数据 * front(); // 返回首元素 * back(); // 返回尾元素 */ #include <iostream> #include <deque> using namespace std; void test0() { deque<int> d; d.push_back(10); d.push_back(20); d.push_back(30); d.push_front(100); d.push_front(200); d.push_front(300); cout << "d = "; for (int i = 0; i < d.size(); i++) { cout << d.at(i) << " "; } cout << endl; cout << "d = "; for (int i = 0; i < d.size(); i++) { cout << d[i] << " "; } cout << endl; cout << "d.front() = " << d.front() << endl; cout << "d.back() = " << d.back() << endl; } int main() { test0(); return 0; }
deque 排序
原型:
- sort(iterator beg, iterator end); // 对[beg, end)区间内的元素进行排序
需要包含
sort排序支持所有随机访问迭代器的容器(eg. vector),都可以利用sort算法直接进行排序
-
示例
cpp// deque的排序 /** * sort(iterator beg, iterator end); // 对[beg, end)区间内的元素进行排序 */ #include <iostream> #include <deque> #include <algorithm> using namespace std; void print_deque(const deque<int>& d) { for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { deque<int> d; d.push_back(10); d.push_back(20); d.push_back(30); d.push_front(100); d.push_front(200); d.push_front(300); cout << "d = "; print_deque(d); // 排序 默认升序 sort(d.begin(), d.end()); cout << "d = "; print_deque(d); } int main() { test0(); return 0; }