一、栈和队列
以上是栈、队列以及优先级队列的常见接口,但在优先级队列中一般默认是大的数据优先级高,优先访问。
二、栈的实现
在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
相关推荐
灯澜忆梦7 小时前
【面向对象编程c++】| 数组与函数起个名字费劲死了7 小时前
VisionMaster 十二点标定+单点抓取Lzg_na9 小时前
僵尸进程、孤儿进程、守护进程:含义、区别与生命周期详解zhanghaha13149 小时前
C++ 的类是什么(新手保姆讲解,配合 Qt 对照理解)aqiu1111119 小时前
【C++算法打怪专栏】LeetCode 402. 移掉 K 位数字(单调栈 + 贪心)(Charon)10 小时前
【C++面试】线程并发与异步:区别、实现原理及使用场景JMchen10 小时前
实战项目一——实现一个高性能图片滤镜App码匠许师傅10 小时前
【C++三方组件】libpqxx:PostgreSQL 的 C++ 客户端H.莓飛11 小时前
【C++】内存管理longlongzihan11 小时前
从LeetCode 19. 删除链表的倒数第 N 个结点深入理解“哨兵节点”










