一、栈和队列
以上是栈、队列以及优先级队列的常见接口,但在优先级队列中一般默认是大的数据优先级高,优先访问。
二、栈的实现
在cpp标准库中,stack是一个模板类,stack本身并不是直接管理数据,而是通过适配器模式将其他容器作为其底层存储机制,在默认情况下其使用的是deque(双端队列)作为其底层容器,当然也可以使用其他容器作为其底层容器。如下图所示简介一下deque的方法。
栈的代码实现
cpp#include <iostream> using namespace std; #include <deque> namespace asy { template<class T,class Container=deque<T>> class myStack { public: void push(const T& val) { _con.push_back(val); } bool empty() { return _con.empty(); } const T& top() { return _con.back(); } //栈:先进后出,栈顶先出 void pop() { _con.pop_back(); } size_t size(){ return _con.size(); } private: Container _con; }; void fun1() { myStack<int> s1; s1.push(1); s1.push(2); s1.push(3); s1.push(4); while (!s1.empty()) { cout << s1.top() << " "; s1.pop(); } cout << endl; } }如上图,通过底层使用deque实现了与stack相同的行为。在这里如果不直接说明则底层是deque,也可以通过vector实现,如下图
三、队列的实现
这里队列的实现依然是使用deque作为底层(默认情况下),也可以指定其他容器作为底层实现。
cpp#pragma once #include <iostream> using namespace std; #include <deque> namespace asy { template<class T, class Container = deque<T>> class queue { public: void push(const T& val) { _con.push_back(val); } const T& top() { return _con.front(); } const T& back() { return _con.back(); } void pop() { _con.pop_front(); } bool empty() { return _con.empty(); } size_t size() { return _con.size(); } private: Container _con; }; void test1() { queue<int> q1; q1.push(1); q1.push(2); q1.push(3); q1.push(4); while (!q1.empty()) { cout << q1.top() << " "; q1.pop(); } cout << endl; } }四、仿函数
在学习优先级队列实现之前先了解什么是仿函数。在cpp中仿函数是指那些重载了()运算符的对象,仿函数本质上是一个像函数一样被调用的类或对象,通过重载operator()运算符实现。
cppnamespace category { struct less { bool operator()(int x, int y) { return x < y; } }; struct gerater { bool operator()(int x, int y) { return x > y; } }; struct add { int operator()(int x,int y) { return x + y; } }; }如上所示,在命名空间category中定义一个结构体,在结构体中重载operator()运算符,此时less和greater和add就是类型(就像int一样)。
如上图,仿函数的使用类似定义一个less类型的函数,然后将数据放在这个函数里面。那么如何将仿函数支持泛型的比较呢?这里就需要仿函数支持模板。如下图所示。
五、优先级队列
cpptemplate<class T,class Container=vector<T>> class priority_queue { public: void AdjustUp(int child) { int parent = (child - 1) / 2; while (child > 0) { if (_con[child] < _con[parent]) { swap(_con[child], _con[parent]); child = parent; parent = (child - 1) / 2; } else { break; } } } void AdjustDown(int parent) { int child = parent * 2 + 1; if (child + 1 < _con.size() && _con[child + 1] < _con[child]) { child++; } if (_con[child] < _con[parent]) { swap(_con[child], _con[parent]); parent = child; child = parent * 2 + 1; } else { break; } } void push(const T& val) { _con.push_back(val); AdjustUp(_con.size() - 1); } void pop() { assert(_con, empty()); swap(0, _con.size() - 1); _con.pop_back(); AdjustDown(0); } const T& top() { return _con.front(); } size_t size() { return _con.size(); } bool empty() { return _con.empty(); } private: Container _con; };如上图所示,每次push数据时都会调用向上调整算法以及每次pop数据时调用向下调整算法使得整个队列保持小堆的形态。
如上图,将仿函数的使用应用到调整算法中。
代码结果如上图所示,在代码77行默认的是less类型仿函数,因此最终结果就是小堆,当然通过如下方法可以修改为大大堆排列。
也可以这样指定仿函数类型:
stack&queue
想成为cpp糕手2025-01-11 21:10
相关推荐
luj_17687 小时前
桥牌思维启示:系统设计的模块化架构会周易的程序员8 小时前
aiDgePLC iec61131 虚拟机 完整使用文档小小龙学IT8 小时前
Boost.Beast 深度实战:基于 Asio 的开源 C++ HTTP/WebSocket 协议库不可求~9 小时前
C++ std::string_view 不是字符串:从悬空引用到安全用法小小龙学IT10 小时前
C++ 正则表达式完全指南:从 std::regex 实战到 RE2 引擎原理(NFA/DFA/回溯陷阱)码匠许师傅13 小时前
【C++ 面试真题】聊聊 C++ 的序列容器C++ 老炮儿的技术栈14 小时前
Qt5.9.1 Windows 完整开发环境搭建流程欧特克_Glodon14 小时前
OpenCV计算机视觉开发入门与实践<十一>:矩阵的复制和矩形类Rect键盘会跳舞14 小时前
C++:std::tuple 源码级深度拆解——变参模板、SFINAE与模板元编程核心技巧bkspiderx15 小时前
从零开始:VS Code搭建C/C++开发环境全指南(Windows/macOS/Linux)










