容器适配器

容器适配器,可以理解为“容器的容器”,或者说将将不适用的容器变得适用,主要是针对序列式容器。

STL的容器适配器包括三大类:

名称描述可以满足条件的容器默认底层容器
stack栈,经典的后进先出(LIFO)deque、list、vectordeque
queue队列,经典的先进先出(FIFO)deque、listdeque
priority_queue优先队列,会自动排序的队列,遵循"先进,优先级最大的元素先出"的规则deque、vectorvector

Stack

Stack是一种名为栈的数据结构,通常用来存储具有“先进后出”数据结构的数据,其本质仍然是线性表,只不过只允许在表的尾端插入与删除

stack位于<stack>头文件中,使用需要:

#include<stack>
using namespace std;

API

创建栈及其初始化
1.构造函数
stack<T> s;//创建数据类型为T的栈,T可以是任意数据类型(包括结构),并且底层采用默认的deque
2.修改底层实现的构造函数
stack<T,Container<T>> s;//Container可以是STL中任意实现了栈对应操作的STL容器,这里包括vector、deque和list
3.用基础容器构造
Container<T> cc{value1,value2...};
stack<T,Container<T>> s(cc);
//Container可以是STL中任意实现了栈对应操作的STL容器,这里包括vector、deque和list
//T与Container必须一致
4.拷贝构造函数
stack<T,Container<T>> s;
stack<T,Container<T>> ss(s);
//T与Container必须一致

//way1
stack<int> s;
//way2
stack<int, vector<int>> ss;
//way3
list<int> L{ 1,2,3 };
stack<int, list<int>> sss(L);//注意栈顶是3
//way4
stack<int, vector<int>> s2;
stack<int, vector<int>> s3(s2);
push

把数据元素压入栈

s.push('a');//把字符a压入栈
pop

把数据元素出栈

s.pop();//栈顶出栈,注意栈空时调用该函数会报错
empty

判断栈是否为空

s.empty();//为空则返回true,否则为false
top

返回栈顶元素

s.top();//返回值为栈顶元素
size

返回栈内的元素个数

s.size();//返回栈内的元素个数
emplace

在栈顶直接构造元素

s.emplace('a');//在栈顶直接构造字符a,速度比push快
swap

在两个栈的<T>Container<T>一致的前提条件下交换两个栈

swap(s,ss);

Queue

Queue是一种名为队列的数据结构,通常用来存储具有“先进先出”数据结构的数据,其本质仍然是线性表,只不过只允许在表的一端插入,在表的另外一段删除

队列位于<queue>头文件中,使用需要:

#include<queue>
using namespace std;

API

创建队列及初始化
1.构造函数
queue<T> q;//创建数据类型为T的队列,T可以是任意数据类型(包括结构),默认底层为deque
2.修改底层实现的构造函数
queue<T,Container<T>> q;//Container可以是STL中任意实现了栈对应操作的STL容器,这里包括deque和list
3.用基础容器构造
Container<T> cc{value1,value2...};
queue<T,Container<T>> q(cc);
//Container可以是STL中任意实现了栈对应操作的STL容器,这里包括vector、deque和list
//T与Container必须一致
4.拷贝构造函数
queue<T,Container<T>> q;
queue<T,Container<T>> qq(q);
//T与Container必须一致

//way1
queue<int> q;
//way2
queue<int, list<int>> qq;
//way3
list<int> L{ 1,2,3 };
queue<int, list<int>> qqq(L);//注意队头是3
//way4
queue<int, list<int>> q2;
queue<int, list<int>> q3(q2);
push

把数据元素压入队列

q.push('a');
pop

把数据元素弹出队列

q.pop();
empty

判断队列是否为空

q.empty();
front

返回队列头元素

q.front();
back

返回队尾元素

q.back();
size

返回队列内元素个数

q.size();
emplace

在队列尾直接创建元素

q.emplace('a');
swap

在两个队列的<T>Container<T>一致的前提条件下交换两个队列

swap(q,qq);

priority_queue

称为优先队列,是一种模拟了队列的数据结构,但是与queue不同,每次只能访问队头

同时,stack和queue在加入元素后不会对其进行排序,都是直接加入末尾,但是优先队列每加入一个新元素都会实现一次排序,将新元素插入排好序的位置中,并且优先队列总是优先级最大的在队头,优先级小的在队尾

因此,优先队列是一种先入,但不一定先出,优先级最大的先出队的结构

因为优先队列与另外两者相比比较特殊,这里给出其定义:

template <typename T,
        typename Container=std::vector<T>,
        typename Compare=std::less<T> >
class priority_queue{
    //......
}

构造一个优先队列需要三个参数,其中2 3个都有默认值,分别为vector和less,前者表示底层采用vector构造,后者表示优先队列采取less(降序)排序,此时队头为最大元素,又称大根堆。与其他STL容器的排序规则一样,这里的排序规则也可以自定义或者使用已封装好的其他排序规则

优先队列位于<queue>头文件中,使用需要:

#include<queue>
using namespace std;

优先队列的底层实现

priority_queue排序以及存储的实现,得益于堆这一数据结构

堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆 (左图所示) 或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆(右图所示)。

堆这一数据结构具有一个重要性质:根结点一定是整个树中的最大(最小)值对应的结点。

另外,对于同一父节点下的子节点一般不要求次序。

优先队列实现自定义排序

对于非基本数据类型,要想实现插入优先队列,首先就要解决排序问题

方法1:函数对象

typedef struct cmp {//函数对象实现
	bool operator ()(const Stu& stu1, const Stu& stu2) const {
		if (stu1.age == stu2.age) {
			return stu1.name < stu2.name;
		}
		return stu1.age < stu2.age;
	}
};

方法2:重载<或者>,借助less或greater实现,该方法对指针类型不适用,less对应<,greater对应>

bool operator < (const Stu& stu1, const Stu& stu2){//重载<实现less
	if (stu1.age == stu2.age) {
		return stu1.name < stu2.name;
	}
	return stu1.age < stu2.age;
}

完整代码:

typedef struct Stu {
	string name;
	int age;
	friend ostream& operator << (ostream& os, const Stu& stu) {
		os << stu.name << ' ' << stu.age << endl;
		return os;
	}
};
typedef struct cmp {//函数对象实现
	bool operator ()(const Stu& stu1, const Stu& stu2) const {
		if (stu1.age == stu2.age) {
			return stu1.name < stu2.name;
		}
		return stu1.age < stu2.age;
	}
};
bool operator < (const Stu& stu1, const Stu& stu2){//重载<实现less
	if (stu1.age == stu2.age) {
		return stu1.name < stu2.name;
	}
	return stu1.age < stu2.age;
}
int main() {
	priority_queue<Stu,vector<Stu>, cmp> pq;
	Stu s[3]{ { "a",1 } ,{"b",2},{"c",1} };
	for (int i = 0; i < 3; i++) pq.emplace(s[i]);
	while (!pq.empty()) {
		cout << pq.top();
		pq.pop();
	}
	priority_queue<Stu> pq2;
	for (int i = 0; i < 3; i++) pq2.emplace(s[i]);
	while (!pq2.empty()) {
		cout << pq2.top();
		pq2.pop();
	}
}

API

创建优先队列及初始化

1.构造函数
priority_queue<T> q;//创建数据类型为T的队列,T可以是任意数据类型(包括结构),默认底层为deque
2.修改底层实现以及排序规则的构造函数
priority_queue<T,Container<T>,cmp> q;//Container可以是STL中任意实现了栈对应操作的STL容器,这里包括deque和vector
3.用基础容器构造
Container<T> cc{value1,value2...};
priority_queue<T,Container<T>> q(begin,end);
//Container可以是STL中任意实现了栈对应操作的STL容器,这里包括vector、deque
//T与Container必须一致
//注意这里只能使用迭代器或者指针,范围为[begin,end),元素在优先队列中的顺序与插入顺序、原有顺序无关
4.拷贝构造函数
priority_queue<T,Container<T>> q;
priority_queue<T,Container<T>> qq(q);
//T与Container必须一致

//way1
priority_queue<int> pq;
//way2
priority_queue<int, deque<int>,greater<int>> pq2;//需要注意,greater在function头文件中
//way3
deque<int> L{ 1,2,3 };
priority_queue<int> sss(L.begin(),L.end());
//way4
priority_queue<int, vector<int>> s2;
priority_queue<int, vector<int>> s3(s2);
push

往优先队列中加入元素

pq.push(1);
pop

弹出优先队列对头

pq.pop();
empty

判断优先队列是否为空

pq.empty();
size

返回优先队列中的元素个数

pq.size();
emplace

在优先队列正确的位置构造元素

pq.emplace(1);
swap

在两个优先队列的<T>Container<T>和比较规则一致的前提条件下交换两个优先队列

swap(pq1,pq2);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值