提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
stack 的介绍和使用
-
stack 对应数据结构中的栈,其只能从容器的一端进行元素的插入和提取操作(先进后出)
-
stack 是一种容器适配器,其能够适配的容器有 vector、list 和 deque(双端队列),如果不指定其适配的容器,默认为 deque
stack 的构造函数
stack (const container_type& ctnr = container_type());
//其中 container_type() == deque
stack<int> st1;
stack<int, vector<int>> st2; //vector 作为底层适配器
stack<int, list<int>> st3; //list 作为适配器
stack 的成员函数
成员函数 | 作用 |
---|---|
bool empty() const | 判断栈是否为空 |
size_t size() const | 获取栈中的元素个数 |
T& top() | 获取栈顶元素 |
void push(const T& val) | 入栈 |
void pop() | 出栈 |
void swap() | 交换两个栈中的数据 |
⭕️注意:由于 stack 的特殊结构(FILO),stack 并没有其他成员函数,也没有迭代器
示例:
#include <stack>
#include <vector>
#include <list>
stack<int> st;
st.push(1);
st.push(2);
st.push(3);
cout << st.top(); //3
st.pop();
cout << st.top(); //2
queue 的介绍和使用
-
queue 对应数据结构中的队列,其在容器中的一端插入元素,在另一端提取元素(先进先出)
-
queue 也是一种容器适配器,其能够适配的容器有 vector、list 和 deque(双端队列),如果不指定其适配的容器,默认为 deque
queue 的构造函数
🍀queue 的构造类似于 stack,这里不多赘述
queue (const container_type& ctnr = container_type());
queue<int> que1;
queue<int, vector<int>> que2;
queue<int, list<int>> que3;
queue 的成员函数
成员函数 | 作用 |
---|---|
bool empty() const | 判断队列是否为空 |
size_t size() const | 获取队列中的元素个数 |
T& front() | 获取队头元素 |
T& back() | 获取队尾元素 |
void pop() | 对头出队列 |
void push(const T& val) | 队尾入队列 |
void swap() | 交换两个队列中的数据 |
⭕️注意:由于 queue的特殊结构(FIFO),queue 并没有其他成员函数,也没有迭代器
示例:
#include <queue>
#include <list>
#include <vector>
queue<int, list<int> que;
que.push(1);
que,push(2);
que.push(3);
que.push(4);
cout << que.front(); //1
cout << que.back(); //4
que.pop();
cout << que.front(); //2
priority_queue 的介绍和使用
-
priority_queue 叫做优先级队列,其对应数据结构中的堆,即其构成的二叉树中,每个节点都比其左右子树大(小),根节点为整个堆的最大值(最小值),如下:
-
priority_queue 也是一个容器适配器。数据结构中,堆的二叉树存放在数组中,所以 priority_queue 默认以 vector 容器作为底层适配器。除此之外,deque 也可以作为适配器
-
堆有大堆(每个节点都比其左右子树大)和小堆(每个节点都比其左右子树小)之分,默认情况下 priority_queue 为大堆
std::less() 和 std::greater()
🍀在 C++ 标准库中,std::less<T> 和 std::greater<T> 是两个常用的比较函数对象(仿函数),它们用于提供比较操作。它们在<functional> 头文件中定义,并且可以与标准算法一起使用
std::less<T>() 的介绍和使用
-
std::less<T> 是一个模板结构体,用于定义小于比较。它的主要功能是在两个值之间执行小于操作(即 a < b)。下面是 std::less 的主要特征:
-
std::less<T> 常用于 STL 容器中排序等的操作。例如,在 list 和 set 容器中,默认情况下使用 std::less<T> 来比较元素,以确保元素按照升序排列
#include <functional>
#include <list>
cout << std::less<int>(3, 4); //1(true)
cout << std::less<int>(4, 3); //0(false)
list<int> lst = {1, 4, 3, 2};
lst.sort(less<int>); //升序排序
//其实 list 的 sort 默认参数就是 less<T>
template <class T>
template <class Compare = bool(const T&, const T&)>
void list<T>::sort(Compare comp = less<T>);
std::less<T> 的模拟实现
namespace yw {
template <class T>
struct less {
operator()(const T& val1, const T& val2)const {
return val1 < val2;
}
};
}
std::greater<T> 的介绍和使用
-
std::greater<T> 是一个模板结构体,用于定义大于比较。它的主要功能是在两个值之间执行大于操作(即 a > b)
-
其用法同 std::less<T>,这里不多赘述
#include <functional>
using namespace std;
cout << greater<int>(1, 2); //0(false)
cout << greater<int>(2, 1); //1(true)
list<int> lst = {1, 4, 3, 2};
lst.sort(greater<int>); //降序排序
std::greater<T> 的模拟实现
namespace yw {
template <class T>
struct greater {
operator()(const T& val1, const T& val2)const {
return val1 > val2;
}
};
}
priority_queue 的构造函数
//默认构造函数
priority_queue (const Compare& comp = Compare(), const Container& ctnr = Container());
//大堆
priority_queue<int> pri_que1;
priority_queue<int, deque<int>> pri_que2;
priority_queue<int, deque<int>, less<int>> pri_que3;
//小堆
priority_queue<int, greater<int>> pri_que4;
priotity_queue<int, deque<int>, greater<int>> pri_que5;
//将 [first, last) 区间元素构成堆
template <class InputIterator>
priority_queue (InputIterator first, InputIterator last, const Compare& comp = Compare(), const Container& ctnr = Container());
vector<int> vtr = {1, 2, 4, 6, 9};
//大堆
priority_queue<int> pri_que1(vtr.begin(), vtr.end());
//小堆
priority_queue<int, greater<int>> pri_que4(vtr.begin(), vtr.end());
priority_queue 的成员函数
常用成员函数
成员函数 | 作用 |
---|---|
void push(const T& val) | 插入到堆中变成叶子节点(并调整成堆) |
void pop() | 取出堆的跟节点(并调整成堆) |
T& top() | 访问堆的根节点元素 |
size_t size() const | 返回堆的元素个数 |
bool empty() const | 判断堆是否为空 |
void swap() | 交换两个堆 |
示例:
#include <queue> //priority_queue 在 queue 头文件中
vector<int> vtr = {12, 4, 7, 20, 17, 9, 1};
//大堆
priority_queue<int, vector<int>, less<int>> pri_que(vtr.begin(), vtr.end());
🍀上面代码建堆过程:
cout << pri_que.top(); //20
pri_que.push(36);
🍀上面代码插入过程:
cout << pri_que.top(); //36
pri_que.pop();
cout << pri_que.top(); //20
🍀上面代码删除过程:
emplace()
🍀与 list 容器中的用法一样,这里不多介绍
template <class... Args>
void emplace(Args&&... args);
priority_queue<vector<int>> pri_que;
pri_que.emplace(1, 2, 3, 4, 5);
vector<int> vtr = pri_que.top();
for(auto e : vtr) {
cout << e << ' ';
} //1 2 3 4 5
stack 模拟实现
stack.h 文件
#pragma once
#include <deque>
using std::deque;
namespace yw {
template <class T, class Container_Type = deque<T>>
class stack {
public:
stack(const Container_Type& cntr = Container_Type()) :_cntr(cntr) {}
void push(const T& val) {
_cntr.push_back(val);
}
void pop() {
_cntr.pop_back();
}
T& top() {
return _cntr.back();
}
const T& top()const {
return _cntr.back();
}
size_t size()const {
return _cntr.size();
}
bool empty()const {
return _cntr.empty();
}
void swap(stack& st) {
_cntr.swap(st._cntr);
}
private:
Container_Type _cntr;
};
}
queue 的模拟实现
queue.h 文件
#pragma once
#include <deque>
using std::deque;
namespace yw {
template <class T, class Container_Type = deque<T>>
class queue {
public:
queue(const Container_Type& cntr = Container_Type()) :_cntr(cntr) {}
void push(const T& val) {
_cntr.push_back(val);
}
void pop() {
_cntr.pop_front();
}
T& back() {
return _cntr.back();
}
const T& back()const {
return _cntr.back();
}
T& front() {
return _cntr.front();
}
const T& front()const {
return _cntr.front();
}
size_t size()const {
return _cntr.size();
}
bool empty()const {
return _cntr.empty();
}
void swap(queue& que) {
_cntr.swap(que._cntr);
}
private:
Container_Type _cntr;
};
}
priority_queue 的模拟实现
🍀priority_queue 实现的重点是建堆和堆调整算法,这里我们只实现大堆的相关算法
priority_queue.h 头文件
#pragma once
#include <vector>
using std::vector;
namespace yw {
template <class T, class Container_Type = vector<T>, class Compare = std::less<T>>
class priority_queue {
public:
//构造函数
priority_queue(const Container_Type cntr = Container_Type(), const Compare comp = Compare())
:_cntr(cntr)
, _comp(comp)
{}
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last, const Container_Type cntr = Container_Type(), const Compare comp = Compare()) {
_cntr = cntr;
_comp = comp;
for (InputIterator it = first; it != last; it++) {
_cntr.push_back(*it);
}
//建堆
BulidHeap(_cntr.size());
}
void push(const T& val) {
_cntr.push_back(val);
AdjustUpHeap(_cntr.size() - 1);
}
void pop() {
::swap(_cntr.front(), _cntr.back());
_cntr.pop_back();
AdjustDownHeap(0, _cntr.size());
}
T& top() {
return _cntr.front();
}
const T& top()const {
return _cntr.front();
}
size_t size()const {
return _cntr.size();
}
bool empty()const {
return _cntr.empty();
}
private:
Container_Type _cntr; //容器适配器
Compare _comp; //比较方式
//建堆
void BulidHeap(size_t n) {
for (int start = n / 2; start >= 0; start--) {
AdjustDownHeap(start, n);
}
}
//向下调整(用于建堆和删除)
void AdjustDownHeap(int start, size_t n) {
T val = _cntr[start];
//start * 2 + 1 是因为 vector 的下标从 0 开始
for (int i = start * 2 + 1; i < n; i = i * 2 + 1) {
if (i + 1 < n && _comp(_cntr[i], _cntr[i + 1]))
i++;
}
if (_comp(val, _cntr[start])) {
_cntr[start] = _cntr[i];
start = i;
}
else break;
}
_cntr[start] = val;
}
//向上调整,用于插入
void AdjustUpHeap(int start, size_t n) {
for (int i = start; i > 0; i /= 2) {
if (_comp(_cntr[i / 2], _cntr[i]))
std::swap(_cntr[i / 2], _cntr[i]);
else break;
}
}
};
}
🍀说明:由于上面三个容器比较简单,所以这里就不进行测试了
本篇文章到这里就结束了,欢迎批评指正!