C++——stack, queue, priority_queue的介绍和模拟实现

1、容器适配器

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

例如:

2、deque(双端队列)

deque是一种双开口的“连续”空间的数据结构,可以在头尾两端进行插入和删除操作,时间复杂度为O(1)

deque并不是真正的连续空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组

双端队列的实现:指针数组(每一个元素缓冲区的首地址)+缓冲区(每一个缓冲区都是定长的,大小相同)

deque的优点:增容代价小,头插头删效率高——O(1),支持随机访问(访问效率比vector略低),相对于list不容易产生内存碎片

缺陷:不适合遍历,中间位置插入和删除效率比较低

3、stack

stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,只能从容器的一端进行元素的插入与提取操作

stack的底层容器应该支持以下操作:empty(判空)、back(获取尾部元素)、push_back(尾插)、pop_back(尾删)

标准容器vector、deque、list均符合这些操作,默认使用deque

stack的操作:

  • stack()——构造空栈;
  • empty()——判空;
  • size()——返回stack元素个数;
  • top()——返回栈顶元素;
  • push()——元素入栈
  • pop()——出栈

接口测试:

stack的模拟实现:

template <class T, class container=deque<T>>
class Stack
{
public:
	void push(const T& val)
	{
		_v.push_back(val);
	}

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

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

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

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

private:
	container _v;
};

模拟实现接口测试:

4、queue

队列是一种容器适配器,专门用于先进先出的操作,从容器一端插入元素,另一端提取元素

queue的底层容器应该支持以下操作:empty(判空)、front(返回对头元素)、back(返回队尾元素)、push_back(尾插)、pop_front(头删)、size(返回元素个数)

标准容器deque、list均符合这些操作,默认使用deque

queue的操作:

  • queue()——构造空队列;
  • empty()——判空;
  • size()——返回队列有效元素个数;
  • front()——返回对头元素;
  • back()——返回队尾元素
  • push()——元素入队
  • pop()——出队

接口测试:

queue的模拟实现:

template <class T, class container=deque<T>>
class Queue
{
public:
	void push(const T& val)
	{
		_lst.push_back(val);
	}

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

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

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

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

	size_t size()
	{
		return _lst.size();
	}
private:
	container _lst;
};

模拟实现接口测试:

5、priority_queue

优先队列是一种容器适配器

priority_queue的底层容器应该支持以下操作:empty(判空)、front(返回第一个元素)、push_back(尾插)、pop_back(尾删)、size(返回元素个数)

标准容器deque、vector均符合这些操作,默认使用vector,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此,priority_queue就是堆

注意:默认情况下,priority_queue是大堆

优先级队列:

比较规则->仿函数类

仿函数类->必须重载  返回值 operator() (参数列表)

数据的比较:内置类型:本身支持大于小于比较;自定义类型:需重载<,>运算符

仿函数类:

使用方式类似于函数调用:

完整:仿函数对象.operator()(参数列表)

简写形式:仿函数对象(参数列表)

priority_queue的操作:

  • priority_queue()/priority_queue(first, last)——构造空优先级队列;
  • empty()——判空;
  • top()——返回堆顶元素
  • push()——元素入队
  • pop()——出队

接口测试:

priority_queue模拟实现

//仿函数类
template <class T>
struct Less
{
	bool operator()(const T& val1,const T& val2)
	{
		return val1 < val2;
	}
};

template <class T>
struct Greater
{
	bool operator()(const T& val1, const T& val2)
	{
		return val1 > val2;
	}
};

template <class T, class Container = vector<T>, class Compare=Less<T>>
class PriorityQueue
{
public:
	void shiftUp(int child)
	{
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			if (_com(_c[parent], _c[child]))
			{
				swap(_c[parent], _c[child]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
				break;
		}
	}

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

	void pop()
	{
		swap(_c[0], _c[_c.size() - 1]);
		_c.pop_back();
		shiftDown(_c[0]);
	}

	T& top()
	{
		return _c.front();
	}

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

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

	void shiftDown(int parent)
	{
		int child = parent * 2 + 1;
		while (child<_c.size())
		{
			if (child+1<_c.size() && _com( _c[child],_c[child+1]))
			{
				child += 1;
			}
			if (_com(_c[parent], _c[child]))
			{
				swap(_c[parent], _c[child]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
				break;
		}
	}

private:
	Container _c;
	Compare _com;
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值