队列:
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
STL中的方法使用:
1.back() 返回一个引用,指向最后一个元素
2.empty() 如果队列空则返回真
3.front() 返回第一个元素
4.pop() 删除第一个元素
5.push() 在末尾加入一个元素
6.size() 返回队列中元素的个数
队列的特点:先进先出。
常用场景:广度优先搜索
队列中有两个值,一个是front去记录队头的位置,另一个是rear去记录队尾的位置。
在实际应用时,由于数组队列的缺点是由于一端插入一端删除,当不断从头部删除数据,头部会大量留有空闲内存,无法插入,造成空间流失,这种属于假溢出的情况。但如果将队头指针在每次删除之后往前移动一个位置,这是一个时间复杂度为O(n)的操作。因此,通常将队列设计为循环队列来克服上述问题。
循环队列可以看作是一个环形结构。有一个maxsize表示数组的长度。当队列未满,并且队头已经到达了maxsize的位置,再次插入数据的时候,队头则从0位置开始插入。
在设计的时候,一般要注意以下几点:
(1)队列初始化时,front和rear值都为零。
(2)当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置。
(3)当队列为空时,front与rear的值相等,但不一定为零。
循环队列满的时候会满足这个计算公式 : (rear+1)%maxsize=front
计算循环队列长度 : (rear-front+maxsize)%maxsize
代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <list>
#include <unordered_map>
#include <cstring>
using namespace std;
int main()
{
queue<int> my_q;
//加入一个元素
my_q.push(1);
my_q.push(2);
my_q.push(3);
//返回一个引用,指向最后一个元素
cout<<my_q.back()<<endl;
//返回第一个元素
cout<<my_q.front()<<endl;
//删除第一个元素
my_q.pop();
return 0;
}
优先队列:
常用场景:取出前K大的数据
一、相关定义
优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认按元素值由大到小排序,可以重载“<”操作符来重新定义比较规则。
二、基本操作
和队列基本操作相同:
- top 访问队头元素
- empty 队列是否为空
- size 返回队列内元素个数
- push 插入元素到队尾 (并排序)
- emplace 原地构造一个元素并插入队列
- pop 弹出队头元素
- swap 交换内容
示例代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <list>
#include <unordered_map>
#include <cstring>
#include<functional> //很关键,不然小顶堆会报错
using namespace std;
//自定义优先级方式
struct cmp{
bool operator ()(int x, int y)
{
return x > y; // x小的优先级高
}
};
int main()
{
//等同于 priority_queue<int, vector<int>, less<int> > my_pq;
priority_queue<int> my_pq; //默认是大顶堆
//priority_queue<int, vector<int>,cmp> my_pq; //自定义优先级方式
//小顶堆
//priority_queue<int, vector<int>, greater<int> > my_pq;
my_pq.push(1);
my_pq.push(2);
my_pq.push(3);
my_pq.push(4);
my_pq.push(5);
my_pq.push(6);
my_pq.push(7);
my_pq.pop();
//剩下三个元素就无法像下面这种方法访问了,所以一般访问第一个元素
for (int i = 0; i < my_pq.size(); ++i) {
cout<<my_pq.top()<<endl;
//删除第一个元素(排序好后的)
my_pq.pop();
}
cout<<my_pq.size()<<endl;
//这样才能正常输出全部数据
// while (my_pq.size()){
// cout<<my_pq.top()<<endl;
// //删除第一个元素(排序好后的)
// my_pq.pop();
// }
return 0;
}
双端队列:
常用场景:实现一个长度动态变化的窗口或者连续区间
deque容器为一个给定类型的元素进行线性处理,像向量一样,它能够快速地随机访问任一个元素,并且能够高效地插入和删除容器的尾部元素。但它又与vector不同,deque支持高效插入和删除容器的头部元素,因此也叫做双端队列。deque类常用的函数如下。
(1) 构造函数
deque():创建一个空deque
deque(int nSize):创建一个deque,元素个数为nSize
deque(int nSize,const T& t):创建一个deque,元素个数为nSize,且值均为t
deque(const deque &):复制构造函数
(2) 增加函数
void push_front(const T& x):双端队列头部增加一个元素X
void push_back(const T& x):双端队列尾部增加一个元素x
iterator insert(iterator it,const T& x):双端队列中某一元素前增加一个元素x
void insert(iterator it,int n,const T& x):双端队列中某一元素前增加n个相同的元素x
void insert(iterator it,const_iterator first,const_iteratorlast):双端队列中某一元素前插入另一个相同类型向量的[forst,last)间的数据
(3) 删除函数
Iterator erase(iterator it):删除双端队列中的某一个元素
Iterator erase(iterator first,iterator last):删除双端队列中[first,last)中的元素
void pop_front():删除双端队列中最前一个元素
void pop_back():删除双端队列中最后一个元素
void clear():清空双端队列中最后一个元素
(4) 遍历函数
reference at(int pos):返回pos位置元素的引用
reference front():返回手元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量头指针,指向第一个元素
iterator end():返回指向向量中最后一个元素下一个元素的指针(不包含在向量中)
reverse_iterator rbegin():反向迭代器,指向最后一个元素
reverse_iterator rend():反向迭代器,指向第一个元素的前一个元素
(5) 判断函数
bool empty() const:向量是否为空,若true,则向量中无元素
(6) 大小函数
Int size() const:返回向量中元素的个数
int max_size() const:返回最大可允许的双端对了元素数量值
(7) 其他函数
void swap(deque&):交换两个同类型向量的数据
void assign(int n,const T& x):向量中第n个元素的值设置为x
示例代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <list>
#include <unordered_map>
#include <cstring>
using namespace std;
int main()
{
deque<int> my_dq;
my_dq.push_back(1);
my_dq.push_back(2);
my_dq.push_back(3);
my_dq.push_back(4);
my_dq.push_back(5);
//删除2
my_dq.erase(my_dq.begin()+1);
while (!my_dq.empty())
{
cout<<my_dq.front()<<endl;
my_dq.pop_front();
}
return 0;
}