当前位置: 首页 > ops >正文

stack和queue简单模拟实现

  • stack
  • reverse_iterator
  • queue
  • priority_queue
    • 仿函数
    • 具体代码

stack

Stacks are a type of container adaptor, specifically designed to operate in a LIFO context (last-in first-out), where elements are inserted and extracted only from one end of the container.

上述描述出自cplusplus.

重点是stack是一个container adaptor也就是容器适配器。
这意味着我们不需要也没有必要从0开始实现stack的方法,而可以通过一个模板,来调用其他容器来实现,以下是stack的部分从成员函数:

template<class T, class Container = deque<int>>
class stack
{
public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}size_t size(){return _con.size();}bool empty(){return _con.empty();}const T& top(){return _con.back();}private:Container _con;
};

可以发现只需要调用传来的模板参数即可。

这里的默认容器是deque,这是一个均衡的容器,整体效率没有vector高,但是可以实现push_front。这是vector做不到的,或者说vector的头插效率是O(n),过低。

值得注意的是,所有容器适配器都不支持迭代器
就以stack举例,如果支持迭代器,那是否意味着破坏了他的FILO特性呢?是的。因此不支持迭代器。

reverse_iterator

上文提到容器适配器,那就不得不提到反向迭代器了。
之前我们实现vector和list的时候都没有实现反向迭代器,因为两者内容过于相似,现在了解了反向迭代器的机制后我们知道,是否可以通过穿入迭代器容器,然后实现反向迭代器。

这意味着,我们可以同时实现所有容器的反向迭代器,也就是实现他们的模板:

template<class Iterator,class Ref,class Ptr>
struct Reverse_iterator
{typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Iterator _it;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){Iterator tmp = _it;return *((--tmp));}Ptr operator->(){return &(operator*());}Self& operator++(){return --_it;}Self& operator--(){return ++_it;}bool operator!=(const Self& it){return _it != it;}};

需要注意的一点是,我们的operator*返回的是 *(--tmp),而不是 *(tmp).

原因是,我们的rbegin()和rend()返回的是end()和begin()。这是基于代码对称性考虑的,正常而言我们的rbegin()和rend()理应返回end()-1和begin()-1.

为了解决这个问题,就只能令operator*返回 *(--tmp)

注:以上实现是visual studio的实现方式。

queue

template<class T, class Container = deque<int>>
class queue
{
public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}size_t size(){return _con.size();}bool empty(){return _con.empty();}const T& front(){return _con.front();}const T& back(){return _con.back();}private:Container _con;
};

priority_queue

priority_queue实质上就是一个堆,并且是默认大根堆。那么我们想要将其改变为小根堆改如何实现?
如果是C语言的话,我们会增加一个函数指针的参数来实现。
在C++中,我们通过传入一个仿函数来实现。

仿函数

所谓仿函数就是指能够像函数一样使用的对象,如下:

template<class T>
class less
{
public:bool operator()(const T& x, const T& y){return x < y;}
};
void test(int x,int y)
{less l;if(l(x,y))cout<<"x<y";else cout<<"x>=y";
}

本质上,我们重载了 (),因此能够将这个对象像函数一样使用。

具体代码

堆的实现,我们已经讲过,这里就不做赘述,感兴趣的读者可以翻阅我前面的文章。

template<class T,class Container=vector<T>,class Compare = less<T>>
class priority_queue
{
public://默认大堆void adjust_up(size_t child){size_t parent = (child - 1) / 2;Compare com;while (child >0){if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);}void adjust_down(size_t parent){size_t child = parent * 2 + 1;while (child<_con.size()){if (child + 1 < _con.size() && com(_con[child],_con[child+1])){++child;}if (com(_con[parent],_con[child])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}bool empty(){return _con.empty();}size_t size(){return _con.size();}const T& top(){return _con[0];}private:Container _con;
};

说起来这里比较奇怪的点是,默认传入less<T>是大根堆,而穿入greater<T>却是小根堆。
但sort穿入,less<T>却是升序排序:

int main()
{vector<int>v = { 1,5,4,3,2 };sort(v.begin(), v.end(),less<int>());//传入less的匿名对象for (auto& e : v)cout << e << ' ';cout << endl;return 0;
}

Output:1 2 3 4 5

http://www.xdnf.cn/news/6806.html

相关文章:

  • 一个可拖拉实现列表排序的WPF开源控件
  • 使用lvm进行磁盘分区
  • LLVM编译器
  • 安装nerdctl和buildkitd脚本命令
  • Go语言深度解析:发展历程、应用场景与性能对比
  • 【springboot+vue3的前后端分离项目实现支付宝的沙箱支付】
  • 从零开始理解Jetty:轻量级Java服务器的入门指南
  • C++跨平台开发:挑战与应对策略
  • Linux:基础IO
  • EXO分布式部署deepseek r1
  • (面试)TCP、UDP协议
  • 38-日语学习小程序
  • 【滑动窗口】P4085 [USACO17DEC] Haybale Feast G|普及+
  • OpenCV透视变换
  • C++学习:六个月从基础到就业——C++11/14:decltype关键字
  • JavaScript进阶(十)
  • 3D个人简历网站 4.小岛
  • Python爬虫(29)Python爬虫高阶:动态页面处理与云原生部署全链路实践(Selenium、Scrapy、K8s)
  • Adobe Illustrator学习备忘
  • 【论文阅读】A Survey on Multimodal Large Language Models
  • MATLAB中进行深度学习网络训练的模型评估步骤
  • 【第一篇】 创建SpringBoot工程的四种方式
  • python field_validator 获取不到参数问题
  • matlab求矩阵的逆、行列式、秩、转置
  • java中的方法详解
  • QML 属性动画、行为动画与预定义动画
  • Python 中的 typing.ClassVar 详解
  • NAT转换和ICMP
  • 前k个高频元素
  • spring框架的JDBC模板技术