容器适配器【stack、queue、priority_queue和反向迭代器】

适配器原理

适配器:适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

stackqueue

虽然stackqueue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为 stackqueue只是对其他容器的接口进行了包装STLstackqueue默认使用deque

deque

deque(double-ended queue,双端队列)是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,相比list增加[]运算符重载。

在这里插入图片描述

详细介绍:deque概述

模拟实现stack

使用vector的接口实现stack的功能

#pragma once

#include <iostream>
#include <vector>

using namespace std;

namespace zwj
{
	template<typename T, typename Contaner = vector<T>>
	class stack
	{
	public:
		size_t size() const
		{
			return _con.size();
		}

		void push(const T& val)
		{
			_con.push_back(val);
		}

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

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

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

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

		void swap(stack& st)
		{
			_con.swap(st._con);
		}


	private:
		Contaner _con;
	};
}

模拟实现queue

使用list的接口实现queue的功能

#pragma once


#include <iostream>
#include <list>

using namespace std;

namespace zwj
{
	template<typename T, typename Contaner = list<T>>
	class queue
	{
	public:
		size_t size() const
		{
			return _con.size();
		}

		void push(const T& val)
		{
			_con.push_back(val);
		}

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

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

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

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

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

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

		void swap(queue& q)
		{
			_con.swap(q._con);
		}


	private:
		Contaner _con;
	};
}

模拟实现priority_queue

优先级队列,底层就是一个堆结构。

priority_queuestackqueue多了一个比较类的函数,默认传的是less<T>(大端),传greater<T>才会是小堆。

在这里插入图片描述

比较类的函数就是重载了operator()的类

#pragma once

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

using namespace std;

namespace zwj
{
	template<typename T, typename Contaner = vector<T>, typename Compare = less<T>>
	class priority_queue
	{
	public:
		void adjust_down(size_t parent)
		{
			assert(parent <= _con.size());

			size_t child = parent * 2 + 1;
			size_t sz = _con.size();
			Compare com;
			while (child < sz)
			{
				if (child + 1 < sz && com(_con[child], _con[child + 1]))
					child++;

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

		void adjust_up(size_t child)
		{
			assert(child < _con.size());

			size_t parent = (child - 1) / 2;
			Compare com;
			while (child > 0)
			{
				if (com(_con[parent], _con[child]))
				{
					::swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		priority_queue()
		{}

		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);
			}
		}


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

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

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

		void push(const T& val)
		{
			_con.push_back(val);
			adjust_up(_con.size() - 1);
		}

		void pop()
		{
			::swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}


		void swap(priority_queue& pq)
		{
			_con.swap(pq._con);
		}

	private:
		Contaner _con;
	};
}

反向迭代器

反向迭代器的功能与正向迭代器是一样的,只是遍历的顺序不同,符合适配器模式,所以可以通过正向迭代器的接口实现反向迭代器。

注意事项:

  1. 正反迭代器的beginend是相对的,所以反向迭代器总是指向需要访问元素的后一个元素
  2. 反向迭代器的 + + = = 正向迭代器的 − − 反向迭代器的++ == 正向迭代器的-- 反向迭代器的++==正向迭代器的
  3. 反向迭代器访问元素之前需要先 − − -- 才行。

list的反向迭代器为例:

template<typename Iterator, typename Ref, typename Ptr>
class __reserve_iterator
{
public:
	typedef __reserve_iterator<Iterator, Ref, Ptr> self;

	// 正向迭代器
	Iterator _cur;

	// 通过正向迭代器构造反向迭代器
	__reserve_iterator(Iterator cur)
		: _cur(cur)
	{}


	// 反向操作
	self& operator++()
	{
		--_cur;
		return *this;
	}

	self operator++(int)
	{
		self tmp(_cur);
		--_cur;
		return tmp;
	}

	self& operator--()
	{
		++_cur;
		return *this;
	}

	self operator--(int)
	{
		self tmp(_cur);
		++_cur;
		return tmp;
	}

	// 先++(反向++)后访问
	Ref operator*()
	{
		auto tmp = _cur;
		--tmp;
		//self tmp(_cur);
		//++tmp;
		return *tmp;
	}

	Ptr operator->()
	{
		return &(operator*());
	}

	bool operator!=(const self& it)
	{
		return _cur != it._cur;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_featherbrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值