一、栈和队列
以上是栈、队列以及优先级队列的常见接口,但在优先级队列中一般默认是大的数据优先级高,优先访问。
二、栈的实现
在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
相关推荐
Growthofnotes几秒前
C++—14、C++ 中的指针最基础的原理bohu8321 分钟前
ros2笔记-4.3 用C++做一个巡逻海龟F-2H2 小时前
C语言:构造类型(共用体/联合体,枚举)qq762118222 小时前
ffmpeg7.0 aac转pcm秋知叶i4 小时前
【轻松学C:编程小白的大冒险】--- 选择 开发工具(IDE)Dev-c++ 03daily_23334 小时前
c++领域展开第十幕——类和对象(内存管理——c/c++内存分布、c++内存管理方式、new/delete与malloc/free区别)超详细!!!!就叫飞六吧4 小时前
C语言中,`extern` 和 `#include`涛ing5 小时前
12. C语言 数组与指针(深入理解)黑果果的思考7 小时前
C++例程:使用I/O模拟IIC接口(6)