C++ 容器适配器 以及 模拟实现stack queue priority_queue

39 篇文章 0 订阅

容器适配器

概念:
适配器是一种设计模式,是将一个类的接口转换成客户希望的另外一个接口。

为什么将stack queue priority_queue称为容器适配器
在STL中并没有将stack queue priority_queue划分在容器的行列,这是因为其他的每个容器在底层都有自己的实现方式,而stack、queue、priority_queue只是在底层将其他容器进行了重新封装

stack适配器的模拟实现
stack在底层用的是双端队列deque

namespace My_Code
{
template<class T, class Container = deque<T>>
class stack
{
public:
	stack()
	{}
	void push(const T& data)
	{
		_con.push_back(data);
	}
	void pop()
	{
		_con.pop_back();
	}
	size_t size()const
	{
		return _con.size();
	}
	bool empty()const
	{
		return _con.empty();
	}
	T& top()
	{
		return _con.back();
	}
	const T& top()const
	{
		return _con.back();
	}
private:
	Container _con;
};
#include<vector>
int main()
{
 bite::stack<int> s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
cout << s.size() << endl;
cout << s.top() << endl;

s.pop();
cout << s.size() << endl;
cout << s.top() << endl;
if (s.empty())
	cout <<"yes" << endl;
else
	cout << "no" << endl;
cout << "以下为s2" << endl;
bite::stack<int, vector<int>> s2;//stack的底层用vector也是可以的。
s2.push(1);
s2.push(2);
s2.push(3);
s2.push(4);
cout << s2.size() << endl;
cout << s2.top() << endl;
s2.pop();
cout << s2.size() << endl;
cout << s2.top() << endl;
if (s2.empty())
	cout << "yes" << endl;
else
	cout << "no" << endl;

在这里插入图片描述

queue适配器的模拟实现
queue在底层用的也是双端队列deque

template<class T, class Container = deque<T>>
class queue
{
public:
	queue()
	{}
	void push(const T& data)
	{
		con.push_back(data);
	}
	void pop()
	{
		con.pop_front();
	}
	size_t size()
	{
		return con.size();
	}
	T& front()
	{
		return con.front();
	}
	const T& front()const 
	{
		return con.front();
	}
	T& back()
	{
		return con.back();
	}
	const T& back()const 
	{
		return con.back();
	}
	bool empty()
	{
		return con.empty();
	}
	private:
	Container con;
};
#include<list>
int main()
{
bite::queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);
cout << q.size() << endl;
cout << q.front() << endl;
cout << q.back() << endl;
q.pop();
cout << q.size() << endl;
cout << q.front() << endl;
cout << q.back() << endl;
cout << "以下为q2" << endl;
bite::queue<int, list<int>>  q2;//queue的底层也可以用list实现
q2.push(5);
q2.push(2);
q2.push(3);
q2.push(4);
cout << q2.size() << endl;
cout << q2.front() << endl;
cout << q2.back() << endl;
q2.pop();
cout << q2.size() << endl;
cout << q2.front() << endl;
cout << q2.back() << endl;
}

在这里插入图片描述
为什么要选用deque来做stack 以及queue配适器的底层默认容器。

  1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
  2. 在stack中元素增长时,deque比vector的效率高(vector需要扩容,效率低);queue中的元素增长时,deque不仅效率高,而且内存使用率高。

priority_queue适配器的模拟实现
priority_queue底层用的是vector

namespace My_Code
{
template<class T,class Container=vector<T>,class compare =less<T>>
class priority_queue
{
public:
	priority_queue()
		:con()
	{}
	template<class Iterator>
	priority_queue(Iterator first, Iterator last)//将输入con中的数据调整成堆,用向下排序法
		: con(first,last)
	{
	   int root = ((con.size() -2)>>1);//因为想要将数组中无序的数,变为堆,就要满足树从下往上都是堆,所以从最后一个非叶子节点开始向下调整。
		//这里的((con.size() -2)>>1)代表的是通过con中最后一个数据的下标来找到其父节点。这个式子实际上是:((con.size()-1)-1)/2
	   for (; root >= 0; root--)//从最后一个非叶子节点开始向根节点遍历,依次进行向下排序。
		{
			AdjustDown(root);
		}
	}
	void push(const T& data)//在数组后面插入一个元素,为了不破坏大堆或者小堆的结构,
		//从最后一个数开始进行一遍向上排序。
	{
		con.push_back(data);
		AdjustUp(con.size()-1);
	}
	void pop()//删除第一个元素。因为底层用的是vector,所以不能直接删除,应将头元素和最后一个元素交换,
		//再进行数组的尾删操作,因为删除后改变了堆,所以从根节点进行向下排序。
	{
		if (empty())
			return;
		swap(con.front(), con.back());
		con.pop_back();
		AdjustDown(0);
	}
	size_t size()const
	{
		return con.size();
	}
	bool empty()const 
	{
		return con.empty();
	}
	const T& top()const
	{
		return con.front();
	}
private:
	void AdjustDown(int parent)//堆的向下调整法
	{
		int child = (parent * 2) + 1;
		while (child < size())
		{
			if (child + 1 < size() && com(con[child], con[child + 1]))
				child += 1;
			if (com(con[parent], con[child]))
			{
				swap(con[parent], con[child]);
				parent = child;
				child = (parent * 2) + 1;
			}
			else
				break;
		}
	}
	void AdjustUp(int child) // 堆的向上调整法
	{
		int parent = ((child - 1) >> 1);
		while (child)
		{
			if (com(con[parent], con[child]))
			{
				swap(con[parent], con[child]);
				child = parent;
				parent = ((child - 1) >> 1);
			}
			else
				return;
		}	
	}
private:
	Container con;
	compare com;
};
}
void Testpriority_queue()
{
int arr[] = { 8 , 1 , 9 , 3 , 6 , 4 , 5 , 0 };
bite::priority_queue<int> Pq(arr,arr+sizeof(arr)/sizeof(arr[0]));
cout << Pq.top() << endl;
Pq.pop();
cout << Pq.top() << endl;
Pq.push(10);
cout << Pq.top() << endl;
}

用区间构造一个优先级队列————大堆。
在这里插入图片描述
分别完成上述三种操作的Pq.top()
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值