C++stack_queue

容器适配器

除了顺序容器外,标准库还定义了三个顺序容器适配器:stack(栈),queue(队列),priority_queue(优先队列)。适配器是标准库中的一个通用概念。容器,迭代器和函数都有适配器。本质上一个适配器是一种机制,能使某种事物的行为看起来像另外一种事情一样。一个适配器接受一种已有的容器类型。使其行为看起来像一种不同的类型。

默认情况下,stack和queue是基于deque(双端队列)实现的,priority_queue是再vector之上实现的。

template <class T, class Container = deque<T> > class stack;
template <class T, class Container = deque<T> > class queue;
template <class T, class Container = vector<T>,
  class Compare = less<typename Container::value_type> > class priority_queue;

我们可以再创建一个适配器时将一个命名的顺序容器作为第二个类型参数,来重载默认的容器类型。

stack<int,vector<int>> stk;
stack<int,list<int>> stk;
queue<int,vector<int>> q;

对一个给定的适配器,可以使用哪些容器是有限制的。所有适配器都要求容器具有添加和删除元素的能力。因此,适配器不能构造再array之上。

stack只要求push_back,pop_back,back操作,可以使用除array和forward_list之外的任何容器类型来构造stack。

queue适配器要求back,push_back,front,push_front,因此它的构造可以构造于list,deque之上,但是不能用vector,因为vector没有push_front等函数,但自己模拟实现的时候,强行用vector也是可以实现的。

priority_queue除了front,push_back,pop_back操作之外,还要求随机访问能力,因此它可以再vector和deque的基础上构造,但不能用list,list不支持随机访问。

stack详解

栈适配器

stack类型定义再stack头文件中,栈所支持的操作不算太多,再之前的数据结构中模拟实现栈的时候,大部分函数已经实现。

在这里插入图片描述

	std::stack<int> stk;//空栈
	stk.push(1);//压栈
	stk.push(2);
	stk.push(3);
	stk.push(4);

	while (!stk.empty()/*判断栈是否为空*/)
	{
		std::cout << stk.top() << ' ';//输出栈顶元素
		stk.pop();//出栈
	}

每个容器适配器都基于底层容器类型的操作定义了自己的特殊操作,我们只可以使用适配器操作,而不能使用底层容器类型的操作。

栈模拟实现

namespace HaiFan
{
	template <class T, class Container = deque<T> > 
	class stack
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}

		T top()
		{
			return _con.back();
		}

		bool empty()
		{
			return _con.empty();
		}

		void pop()
		{
			_con.pop_back();
		}

		size_t size()
		{
			return _con.size();
		}

		void swap(stack<T>& it)
		{
			_con.swap(it._con);
		}
		//swap函数交换的是容器对象,而不是it本身,所以再模拟实现按的时候要注意一下,否则会出现类型不匹配的报错。
	private:
		Container _con;
	};
}

队列详解

队列适配器

queue和priority_queue适配器定义再queue头文件中。

queue

在这里插入图片描述

priority_queue

在这里插入图片描述

标准库queue使用一种先进先出的存储和访问策略。进入队列的对象被放置到队尾,而离开队列的对象则从队首删除。

priority_queue允许我们为队列中的元素建立优先级。新加入的元素会排在所有优先级比他低的已有元素之前。

queue的用法很简单,empty判空,size队列大小,front队首元素,back队尾元素,push入队,pop出队。


优先队列其实是一个堆

	priority_queue<int, vector<int>, greater<int>> q;
	//greater小根堆,less大根堆
	q.push(1);
	q.push(-1);
	q.push(100);
	q.push(120);
	q.push(10);
	
	while (q.size())
	{
		cout << q.top() << ' ';
		q.pop();
	}

在这里插入图片描述

queue模拟实现

#pragma once

#include <deque>

namespace HaiFan
{
	template<class T,class Container = deque<T>>
	class queue
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}

		void pop()
		{
			_con.pop_front();
		}

		T front()
		{
			return _con.front();
		}

		T back()
		{
			return _con.back();
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};
}

priority_queue模拟实现

#pragma once

#include <vector>
#include <assert.h>

namespace HaiFan
{
	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;
		}
	};

	template<class T, class Container = vector<T>, class Compare = Less<T>>
	class priority_queue
	{
	public:
		priority_queue()
		{}

		template<class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				_con.push_back(*first);
				++first;
			}

			for (int i = (int(_con.size()) - 1 - 1) / 2; i >= 0; i--)
			{
				JustDown(i);
			}
		}

		void JustDown(int parent)
		{
			Compare com;
			int 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 JustUp(int child)
		{
			Compare com;
			int parent = (child - 1) / 2;

			while (child > 0)
			{
				if (child + 1 < _con.size() && com(_con[child],_con[child + 1]))
				{
					++child;
				}

				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);
			JustUp(int(_con.size() - 1));
		}

		void pop()
		{
			assert(_con.size() > 0);
			std::swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			JustDown(0);
		}

		const T& top()
		{
			return _con[0];
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值