一、栈和队列
以上是栈、队列以及优先级队列的常见接口,但在优先级队列中一般默认是大的数据优先级高,优先访问。
二、栈的实现
在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
相关推荐
ChoSeitaku1 小时前
12.重复内容去重|添加日志|部署服务到Linux上(C++)挣扎与觉醒中的技术人1 小时前
网络安全入门持续学习与进阶路径(一)OTWOL2 小时前
【C++编程入门基础(一)】宇寒风暖3 小时前
侯捷 C++ 课程学习笔记:内存管理与工具应用Smile丶凉轩3 小时前
数据库面试知识点总结Want5953 小时前
C/C++跳动的爱心laimaxgg3 小时前
Qt常用控件之数字显示控件QLCDNumber蓝天扶光3 小时前
c++贪心系列Alidme4 小时前
cs106x-lecture14(Autumn 2017)-SPL实现小王努力学编程4 小时前
【算法与数据结构】单调队列