C++标准库定义了三个顺序容器适配器:stack、queue和priority_queue。适配器是标准库中的一个通用的概念。容器、迭代器和函数都有适配器。
本质上,适配器是一种机制,能使某物的行为看起来像另外一种事物一样。一个容器适配器接受一种已有的容器类型,使其行为看起来像另外一种事物。例如:stack适配器接受一个顺序容器(array、forward_list除外),使其行为看起来像stack一样。
所有容器适配器都支持的操作:
A a; | 创建一个名为a的空适配器 |
A a(b); | 创建一个名为a的适配器,并且a带有b的拷贝 |
关系运算符 | 都支持:==、!=、<、<=、>、>=。这些运算符返回底层容器的比较结果 |
a.empty() | a为空,返回true,否则返回false |
a.size() | 返回a中元素的数目 |
a.swap(b) swap(a,b); | 交换a,b的内容,a和b必须是相同类型,包括底层容器的类型也必须相同。 |
一、stack
头文件<stack>,实现了先进后出的数据结构。
构造:
template <class T, class Container = deque<T> > class stack;
有两个参数,第一个参数表示栈中存放的数据类型,int、double等;第二个参数表明这个栈的内部实现方式,默认是deque实现。当然我们也可以指明vector或者list。
除了支持表1的操作,还支持:
s.pop() | 删除栈顶元素,但不返回栈顶元素 |
s.push(item) | 将item压入栈顶,该元素通过拷贝或移动item而来 |
s.emplace(args) | 将元素压入栈顶,该元素通过args进行构造 |
s.top() | 返回栈顶元素,但是不删除栈顶元素 |
2、queue
头文件是<queue>,queue使用一种先进先出的存储和访问策略。进入队列的对象被放置在队尾,而离开队列的对象则从队首删除。queue默认基于deque实现,当然,也可以指明为list或者vector。
q.pop() | 删除queue的队头元素 |
q.front() | 返回队头元素,但不删除 |
q.back() | 返回队尾元素,但不删除 |
q.push(item) | 在queue的队尾添加元素 |
q.emplace(args) | 在queue的队尾添加元素,该元素由args构造 |
3、priority_queue
头文件是<queue>,priority_queue允许我们为队列中的元素建立优先级,新加入的元素会排在所有优先级比它低的已有的元素之前。priority_queue默认基于vector实现,当然也可以指明为deque实现。
q.top() | 返回最高优先级元素 |
q.pop() | 删除优先级最高的元素 |
q.push(item) | 在priority_queue的一个恰当位置添加元素 |
q.emplace(args) | 在priority_queue的一个恰当的位置添加元素,该元素由args构造 |
priority_queue<Type, Container, Functional>
其中,Type是数据类型,Container是容器类型(Container必须是用数组实现的容器,如:vector、deque,但是不可以是list),Functional是比较方式。如果是内置类型,可以说使用伪函数less或者greater,默认使用的是less,如果数据类型是自定义类型,则需要自定义比较方式。自定义比较方式类似map。
排序:1)如果是自定义类型,类中实现<运算符的重载;2)伪函数方式,定义class或struct,实现操作符()的重载;3)直接重载<运算符。
class Student{
public:
std::string name_;
int age_;
Student(std::string name, int age):name_(name),age_(age){}
Student(){}
std::string show(){
return "name:" + name_ + ", age:" + std::to_string(age_);
}
bool operator < (const Student &s) const {
std::cout << "operator : < " << std::endl;
if(name_ != s.name_){
return name_ < s.name_;
}else{
return age_ < s.age_;
}
}
};
class Comp{
public:
bool operator () (const Student &left, const Student &right) const {
std::cout << "operator ()" << std::endl;
if(left.name_ != right.name_){
return left.name_ < right.name_;
}else{
return left.age_ < right.age_;
}
}
};
void test_priority_queue(){
vector<Student> v;
v.push_back(Student("aaa", 22));
v.push_back(Student("abb", 22));
v.push_back(Student("aaa", 25));
v.push_back(Student("zzz", 22));
//priority_queue<Student, vector<Student>, Comp> p;
priority_queue<Student> p;
p.push(Student("aaa", 22));
p.push(Student("abb", 26));
p.push(Student("aaa", 25));
p.push(Student("qwe", 22));
while(!p.empty()){
Student s = p.top();
p.pop();
cout << s.show() << endl;
}
}