stack
使用
函数说明 | 接口说明 |
stack() | 构造空的栈 |
empty() | 检测stack是否为空 |
size() | 返回stack中元素的个数 |
top() | 返回栈顶元素的引用 |
push() | 将元素val压入stack中 |
pop() | 将stack中尾部的元素弹出 |
底层实现
#include<vector>
namespace A
{
template<class T>
class stack
{
public:
stack() {}
void push(const T& x) {_c.push_back(x);}
void pop() {_c.pop_back();}
T& top() {return _c.back();}
const T& top()const {return _c.back();}
size_t size()const {return _c.size();}
bool empty()const {return _c.empty();}
private:
std::vector<T> _c;
};
}
//stack.h
#pragma once
#include<deque>
namespace A
{
template<class T, class Con = deque<T>>
class stack
{
public:
void push(const T& x) {
_c.push_back(x);
}
void pop() {
_c.pop_back();
}
T& top() {
return _c.back();
}
const T& top()const {
return _c.back();
}
size_t size()const {
return _c.size();
}
bool empty()const {
return _c.empty();
}
private:
Con _c;
};
};
queue
使用
函数声明 | 接口说明 |
queue() | 构造空的队列 |
empty() | 检测队列是否为空,是返回true,否则返回false |
size() |
返回队列中有效元素的个数
|
front() | 返回队头元素的引用 |
back() | 返回队尾元素的引用 |
push() | 在队尾将元素val入队列 |
pop() | 将队头元素出队列 |
底层实现
#include <list>
namespace A
{
template<class T>
class queue
{
public:
queue() {}
void push(const T& x) {_c.push_back(x);}
void pop() {_c.pop_front();}
T& back() {return _c.back();}
const T& back()const {return _c.back();}
T& front() {return _c.front();}
const T& front()const {return _c.front();}
size_t size()const {return _c.size();}
bool empty()const {return _c.empty();}
private:
std::list<T> _c;
};
}
#pragma once
#include<deque>
namespace A
{
template<class T, class Con = deque<T>>
class queue
{
public:
void push(const T& x) {
_c.push_back(x);
}
void pop() {
_c.pop_front();
}
T& back() {
return _c.back();
}
const T& back()const {
return _c.back();
}
T& front() {
return _c.front();
}
const T& front()const {
return _c.front();
}
size_t size()const {
return _c.size();
}
bool empty()const {
return _c.empty();
}
private:
Con _c;
};
};
适配器模式
什么是适配器
STL标准库中stack和queue的底层结构
deque
deque的简单介绍
结论:vector和list的缝合怪,支持随机访问,头插头删
deque的原理和底层介绍
deque的缺陷
为什么选择deque作为stack和queue的底层默认容器
priority_queue
使用
函数声明 | 接口说明 |
priority_queue()/priority_queue(first,
last)
| 构造一个空的优先级队列 |
empty( ) |
检测优先级队列是否为空,是返回
true
,否
则返回
false
|
top( ) |
返回优先级队列中最大
(
最小元素
)
,即堆顶元
素
|
push(x) | 在优先级队列中插入元素x |
pop() |
删除优先级队列中最大
(
最小
)
元素,即堆顶元
素
|
仿函数
priority_queue
需要一个仿函数来确定元素的优先级顺序。默认情况下,priority_queue
使用 less<T>
作为比较准则,即优先队列后面的元素都要小于优先队列前面的元素,因为优先队列队首的元素优先级最高,优先队列队尾元素的优先级最低,所以小于号<就规定了优先队列后面的元素都要小于优先队列前面的元素(尾部优先级小于首部优先级),也就是形成一个大根堆,降序排序,每次权值最大的会被弹出来。
而通过定义自己的仿函数,用户可以指定 priority_queue
中元素如何相互比较。
priority_queue<int, vector<int>, greater<int>> pq2; //小根堆,升序
在C++中,仿函数是实现了operator()
的类的对象,使得它们可以被像函数一样调用。这实际上是一种重载了()
操作符的类,使得其对象能够表现得像函数一样。
仿函数为C++的泛型编程和STL中的算法和容器提供了强大的灵活性。
定义仿函数
仿函数是通过定义一个类并在其中重载()
操作符来实现的。这个操作符可以接受任意数量和类型的参数(根据需求),并可以返回一个值。
#include <iostream>
// 定义仿函数
class Add {
public:
// 重载()操作符
int operator()(int a, int b) const {
return a + b;
}
};
int main() {
Add add; // 创建仿函数对象
int result = add(5, 3); // 像函数一样调用仿函数对象
std::cout << "The sum is: " << result << std::endl;
return 0;
}
何时使用仿函数
1.类类型不支持比较大小
2.支持比较大小,但是比较的逻辑不是你想要的(例子,date类)
下面的底层实现就运用到了仿函数。
底层实现
#include<vector>
#include<functional>
namespace A
{
template<class T>
class less {
public:
bool operator()(const T& x, const T& y) {
return x < y;
}
};
template<class T>
class greater {
public:
bool operator()(const T& x, const T& y) {
return x > y;
}
};
template <class T, class Container = vector<T>, class Compare = less<T> >
class priority_queue
{
public:
// template <class InputIterator>
// priority_queue(InputIterator first, InputIterator last);
void adjustup(int child) {
Compare comp;
int parent = (child - 1) / 2;
while (child>0) {
if (comp(c[parent] ,c[child])) {
swap(c[parent], c[child]);
child = parent;
parent = (child - 1) / 2;
}
else {
break;
}
}
}
void adjustdown(int parent) {
Compare comp;
int child = parent * 2 + 1;
while (child<c.size()) {
if (child+1<c.size()&&comp(c[child] , c[child + 1])) {
child ++;
}
if (comp(c[parent], c[child])) {
swap(c[parent], c[child]);
parent=child;
child = parent * 2 + 1;
}
else {
break;
}
}
}
bool empty() const {
return c.empty();
}
size_t size() const {
return c.size();
}
const T& top() const {
return c[0];
}
void push(const T& x) {
c.push_back(x);
adjustup(size()-1);
}
void pop() {
swap(c[0], c[size() - 1]);
c.pop_back();
adjustdown(0);
}
private:
Container c;
};
};
算法库中关于堆的算法
sort_heap
用途:进行堆排序
使用注意:函数使用对象必须为堆
is_heap
判断是否为堆
make_heap
建堆算法
push_heap&&pop_heap
push_heap
函数的作用是将位于 [first, last-1)
范围内的元素视为一个堆,并将 *(last-1)
(即最后一个元素)添加到这个堆中,同时重新排列元素以保持堆的性质。
相当于adjustup函数
而pop_heap函数,则相当于adjustdown函数
#include <iostream>
#include <algorithm>
#include <vector>
int main () {
int myints[] = {10,20,30,5,15};
std::vector<int> v(myints,myints+5);
std::make_heap (v.begin(),v.end());
std::cout << "initial max heap : " << v.front() << '\n';
std::pop_heap (v.begin(),v.end()); v.pop_back();
std::cout << "max heap after pop : " << v.front() << '\n';
v.push_back(99); std::push_heap (v.begin(),v.end());
std::cout << "max heap after push: " << v.front() << '\n';
std::sort_heap (v.begin(),v.end());
std::cout << "final sorted range :";
for (unsigned i=0; i<v.size(); i++)
std::cout << ' ' << v[i];
std::cout << '\n';
return 0;