【C++】Stack and Queue and Functor

本文是小编巩固自身而作,如有错误,欢迎指出!

本次我们介绍STL中的stack和queue和其相关的一些容器和仿函数

一.stack and queue

1.适配器

stack和queue其实不是真正意义上的容器,而是容器适配器,而容器适配器又是什么呢?

在C++中,容器适配器(Container Adapters)是一种特殊的容器,它们不提供独立的底层数据存储结构,而是基于其他基础容器(如 vector、deque、list)来实现特定的功能和接口。

简单来说就是之前我们学习的时要了解stack和queue的底层是什么,是数组还是队列,同理在c++就考虑他的底层是vector还是list等等

而在官方给的底层是deque

而deque又是什么呢?

2.deque

全称为"double-ended queue",即双端队列,是 C++ 标准模板库(STL)中的一种容器。

简单来说deque就是vector和list的缝合产物

通过前面的学习我们都知道,vector的尾插时间复杂度比头插小,而list痛点在于不能随机访问,但deque就解决了这个问题

deque 是一种序列容器,它允许在容器的两端快速插入和删除元素,时间复杂度为 O(1)。与 vector 相比,deque 可以在头部和尾部高效地进行元素的插入和删除操作;与 list 相比,deque 支持随机访问元素。

deque的原理类似下图

deque本质其实就是划分一个个个小数组融合成为大数组,其由一个中控数组map操作,而map中储存的就是每个小数组的地址,及其头尾指针等等。

下面是用vector实现的栈和用list实现的队列

cpp 复制代码
#include<vector>
namespace bite
{
 template<class T>
 class stack
 {
 public:
 stack() {}
 void push(const T& x) {_c.push_back(x);}
void pop() {_c.pop_back();}
 T& top() {return _c.back();}
 const T& top()const {return _c.back();}
 size_t size()const {return _c.size();}
 bool empty()const {return _c.empty();}
 private:
 std::vector<T> _c;
 };
}
cpp 复制代码
#include <list>
namespace bite
{
 template<class T>
 class queue
 {
 public:
 queue() {}
 void push(const T& x) {_c.push_back(x);}
 void pop() {_c.pop_front();}
 T& back() {return _c.back();}
 const T& back()const {return _c.back();}
 T& front() {return _c.front();}
 const T& front()const {return _c.front();}
 size_t size()const {return _c.size();}
 bool empty()const {return _c.empty();}
 private:
 std::list<T> _c;
 };
}

二.priority_queue

1.priority_queue简介

在 C++ 中,priority_queue(优先队列) 是一种特殊的容器适配器,它基于堆(Heap)数据结构实现,提供常数时间访问最大/最小元素的能力(默认最大堆)。

我们看下以下用例

cpp 复制代码
#include<iostream>
#include<queue>
using namespace std;
int main()
{
		priority_queue<int> pq;
		pq.push(3);
		pq.push(5);
		pq.push(6);
		pq.push(1);
		pq.push(9);
		while (!pq.empty())
		{
			cout << pq.top();
			pq.pop();
		}
		return 0;
	

}

我们看出来这是系统默认的情况(最大堆),那么如果我们自己实现要自己模拟实现想要最小堆建怎么办呢?

我们先看看模拟实现是什么样的

cpp 复制代码
#pragma once
#include<vector>
template<class T>
class Less
{
public:
	bool operator()(const T& x,const T& y)
	{
		return x < y;
	}

};
template<class T>
class Greater
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x > y;
	}
};
namespace yiming
{
   template<class T,class Container=std::vector<T>,class Compare=Less<T>>
   class priority_queue
   {
   public:
	   priority_queue() = default;
	   template <class InputIterator>
	   priority_queue(InputIterator first, InputIterator last)
		   :con(first,last)
	   {
		   //向下调整建堆
		   for (int i = (con.size() - 1 - 1) / 2;i >= 0;i--)
		   {
			   adjust_down(i);
		   }
	   }


	  
	   void push(const T& x)
	   {
		   con.push_back(x);
		   adjust_up(con.size() - 1);
	   }
	   void pop()
	   {
		   swap(con[0], con[con.size() - 1]);
		   con.pop_back();
		   adjust_down(0);
	   }
	   const T& top()
	   {
		   return con[0];
	   }
	   bool empty()const
	   {
		   return con.empty();
	   }
	   size_t size()const
	   {
		   return con.size();
	   }
   private:
	   void adjust_up(int child)//向上调整
	   {
		   Compare com;
		   int parent = (child - 1) / 2;

		   while (child > 0)
		   {
			   if (com(con[parent], con[child]))
			   {
				   swap(con[child], con[parent]);
				   child = parent;
				   parent = (child - 1) / 2;
			   }
			   else
			   {
				   break;
			   }
		   }
	   }
	   void adjust_down(int parent)
	   {
		   Compare com;
		   size_t child = parent * 2 + 1;
		   while (child < con.size())
		   {
			   if (child + 1 < con.size() && com(con[child], con[child + 1]))//选出最大的child
				   ++child;

			   if (com(con[parent], con[child]))
			   {
			   swap(con[parent], con[child]);
			   parent = child;
			   child = parent * 2 + 1;
			   }
			   else
			   {
				   break;
			   }
		   }
	   }
   private:
	   Container con;
   };
}

其中我们看到了主要决定这个模拟实现的类型就行这样一个模版

cpp 复制代码
   template<class T,class Container=std::vector<T>,class Compare=Less<T>>

我们看到通过这个模版的Compare就可以实现建大堆小堆,这里就涉及到一个概念,仿函数

2.仿函数

仿函数(Functor)是C++中一种行为类似函数的对象,通过重载operator()实现。它可以是普通函数指针、类成员函数指针或定义了operator()的类对象。

其实简单来说就是把一个类包装成函数的样子

如上述代码中的

cpp 复制代码
template<class T>
class Less
{
public:
	bool operator()(const T& x,const T& y)
	{
		return x < y;
	}

};
template<class T>
class Greater
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x > y;
	}
};

这样就可以通过模版来实现改变建大堆小堆了

三.测试代码

cpp 复制代码
int main()
{
priority_queue <int>pq;
	pq.push(4);
	pq.push(5);
	pq.push(2);
	pq.push(5);
	pq.push(6);
	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;


	stack<int> st;
	st.push(1);
	st.push(3);
	st.push(4);
	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl;
	queue<int>q;

	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	while (!q.empty())
	{
		cout << q.front()<<" ";
		q.pop();
	}
	return 0;
}

本次分享就到这里结束了,后续会继续更新,感谢阅读!

相关推荐
CodeCraft Studio2 小时前
PPT处理控件Aspose.Slides教程:在 C# 中将 PPTX 转换为 Markdown
开发语言·c#·powerpoint·markdown·ppt·aspose·ai大模型
萧鼎3 小时前
深入理解 Python Scapy 库:网络安全与协议分析的瑞士军刀
开发语言·python·web安全
阿拉丁的梦5 小时前
教程1:用vscode->ptvsd-创建和调试一个UI(python)-转载官方翻译(有修正)
开发语言·python
木宇(记得热爱生活)5 小时前
一键搭建开发环境:制作bash shell脚本
开发语言·bash
Cisyam^5 小时前
Go环境搭建实战:告别Java环境配置的复杂
java·开发语言·golang
IAR Systems6 小时前
在IAR Embedded Workbench for Arm中实现Infineon TRAVEO™ T2G安全调试
开发语言·arm开发·安全·嵌入式软件开发·iar
jayzhang_7 小时前
SPARK入门
大数据·开发语言
蹦极的考拉7 小时前
网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
android·开发语言·php
fured7 小时前
[调试][实现][原理]用Golang实现建议断点调试器
开发语言·后端·golang
大翻哥哥8 小时前
Python地理空间数据分析:从地图绘制到智能城市应用
开发语言·python·数据分析