队列 std::queue 双端队列 std::deque,优先级队列 std::priorty_queue
一、双端队列 std::deque
std::deque(double-ended queue)双端队列,是有下标的顺序容器。它允许在其首尾两端快速插入及删除。另外,在deque任一端插入或删除不会非法化指向其余元素的指针或引用(例如vector删除第一个元素,其他所有迭代器的值都会指向下一个元素,而deque删除后指向元素为空)
与std::vector相反,deque 的元素不是连续存储的,典型实现:用单独分配的固定大小数组的序列,外加额外的登记,这表示下标访问必须进行二次指针解引用,与之相比vector的下标访问只进行一次。
deque的存储按需自动扩展及收缩。扩张deque比扩张std::vector更优,因为它不涉及复制既存元素到新内存位置。另一方面,deque典型地拥有较大的最小内存开销;只有一个元素的deque必须分配其整个内部数组。
1.构造
std::deque<int> d1{ 1,2,3,4,5 }; //d1 = 1,2,3,4,5
std::deque<int> d2(3, 5); //d2 = 5,5,5
std::deque<int> d3(d1.begin(), d1.begin() + 2); //d3 = 1,2
2.添加
d2.emplace(d2.begin() + 1, 2); //开始的下一个位置添加一个2:5,2,5,5
d2.emplace_back(3); //末尾添加一个3:5,2,5,5,3
d2.emplace_front(4); //首部添加一个4:4,5,2,5,5,3
d2.push_back(6); //末尾添加一个6:{4,5,2,5,5,3,6}
d2.insert(d2.end(), 1);//末尾添加一个1:{4,5,2,5,5,3,6,1}
d2.insert(d2.begin(), { 7,8,9 }); //首部添加一组7,8,9:{7,8,9,4,5,2,5,5,3,6,1}
3.访问
auto ret1 = d2.front();
auto ret2 = d2.back();
auto ret3 = *d2.begin();
auto ret4 = d2[5]; //从0开始第5个
auto ret5 = d2.at(2);//从0开始第2个
//auto r1 = d2.at(100); //崩溃
//auto r2 = d2[100]; //中断
4.删除
d2.pop_back(); //移除最后一个元素
d2.pop_front();//移除第一个元素
d2.erase(d2.begin());//移除指定位置的一个元素(移除第一个元素)
d2.erase(d2.begin(), d2.begin() + 2); //移除指定范围的n个元素(移除前两个元素)
d2.clear();//清空元素
5.其他
函数 | 描述 |
---|---|
empty() | deque为空返回true |
size() | 返回deuqe元素的个数 |
swap(deque&) | 交换两个deque的元素 |
resize(size_t) | 设置deque的元素个数 |
max_size() | 返回deuqe可容纳的最大元素个数 |
示例代码
点击查看代码
#include <list>
#include <deque>
int main()
{
std::deque<int> d1{ 1,2,3,4,5 }; //d1 = 1,2,3,4,5
std::deque<int> d2(3, 5); //d2 = 5,5,5
std::deque<int> d3(d1.begin(), d1.begin() + 2); //d3 = 1,2
d2.emplace(d2.begin() + 1, 2); //开始的下一个位置添加一个2:5,2,5,5
d2.emplace_back(3); //末尾添加一个3:5,2,5,5,3
d2.emplace_front(4); //首部添加一个4:4,5,2,5,5,3
d2.push_back(6); //末尾添加一个6:{4,5,2,5,5,3,6}
d2.insert(d2.end(), 1);//末尾添加一个1:{4,5,2,5,5,3,6,1}
d2.insert(d2.begin(), { 7,8,9 }); //首部添加一组7,8,9:{7,8,9,4,5,2,5,5,3,6,1}
auto ret1 = d2.front();
auto ret2 = d2.back();
auto ret3 = *d2.begin();
auto ret4 = d2[5]; //从0开始第5个
auto ret5 = d2.at(2);//从0开始第2个
//auto r1 = d2.at(100); //崩溃
//auto r2 = d2[100]; //中断
d2.pop_back(); //移除最后一个元素
d2.pop_front();//移除第一个元素
d2.erase(d2.begin());//移除指定位置的一个元素(移除第一个元素)
d2.erase(d2.begin(), d2.begin() + 2); //移除指定范围的n个元素(移除前两个元素)
d2.clear();//清空元素
int test = 0;
return 0;
}
二、队列 std::queue
先进先出,只能队尾插入元素,队首抛出元素
点击查看代码
#include <queue>
int main()
{
std::queue<int> myQueue({ 1, 2, 3 });
myQueue.emplace(4); // 队尾添加一个元素
myQueue.push(5); // 队尾添加一个元素
myQueue.pop(); // 抛出队首元素
auto ret1 = myQueue.empty(); // 判断是否为空
auto ret2 = myQueue.size(); // 元素个数
std::deque<int> myDeque{ 2,3,4 };
std::queue<int> myQueue1(myDeque);
myQueue.swap(myQueue1);// 交换元素
int test = 0;
}
三、优先级队列 std::priorty_queue
要想对自定义数据结构使用优先级队列必须实现对“<”的重载
优先级队列有三个比较重要的成员函数
函数 | 描述 |
---|---|
push(const value_type& value) | 队列尾部添加一个元素 |
top() | 返回权值最大(或最小)的元素 |
pop() | 删除权值最大(或最小)的元素,即删除top()元素,注意:此处不是队首元素 |
示例代码
点击查看代码
#include <iostream>
#include <queue>
#include <map>
class A
{
public:
A(int x) { a = x; }
int a;
bool operator < (const A& aa) const //后置const必须有
{
return aa.a < this->a;
}
};
int main()
{
std::priority_queue<A> p3;
p3.emplace(A(1));
p3.emplace(A(5));
p3.emplace(A(2));
p3.emplace(A(9));
p3.emplace(A(4));
p3.emplace(A(3));
while (!p3.empty())
{
std::cout << p3.top().a << "\n";
p3.pop();
}
std::cout << "========\n";
std::priority_queue<std::pair<int, int>> p2; //按pair的first排序
p2.emplace(1, 1);
p2.emplace(3, 3);
p2.emplace(7, 7);
p2.emplace(8, 2);
p2.emplace(5, 9);
while (!p2.empty())
{
std::cout << p2.top().first << " " << p2.top().second << "\n";
p2.pop();
}
return 0;
}