0
点赞
收藏
分享

微信扫一扫

模拟实现优先级队列超详解(C++)

热爱生活的我一雷广琴 2022-05-01 阅读 77

在这里插入图片描述

😇 😇大家好,我是bug!今天我们来讲讲容器适配器
(代码可能会有一点问题,请各位老铁指正 😘 😘 )

文章目录

容器适配器

一、stack

🌹 🌹 栈: 又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

🌵🌵常用接口:

函数用法
stack()构造空的栈
empty()检测stack是否为空
size()返回stack中元素的个数
top()返回栈顶元素的引用
push()将元素val压入stack中
pop()将stack中尾部的元素弹出

🍒 🍒模拟实现⬇️ ⬇️:

#include<iostream>
#include<queue>

using std::cin;
using std::cout;
using std::endl;
using std::deque;

namespace lz
{
	template<class T,class Container = deque<T>>
	class stack
	{
	private:
		Container _con;

	public:
		stack()
			:_con()
		{}
		//入栈,出栈
		void push(const T& val) { _con.push_back(val); }
		void pop()	{ if (empty()) return; _con.pop_back(); }

		//元素个数,判空
		size_t size() { return _con.size(); }
		bool empty() { return size() == 0; }

		//栈顶数据(可修改和不可修改)
		T& top(){	return _con.back();}
		const T& top()const { return _con.back(); }
	};
}


#include"stack.h"

void Test_stack()
{
	//默认容器:双端队列
	lz::stack<int> s1;
	s1.push(1);
	s1.push(2);
	s1.push(3);
	s1.push(4);
	while (!s1.empty())
	{
		cout << s1.top() << endl;
		s1.pop();
	}
	cout << s1.size() << endl;
}

int main()
{
	Test_stack();
	return 0;
}

二、queue

🌹 🌹队列:一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

🌵🌵常用接口:

函数用法
queue()构造空的队列
empty()检测队列是否为空,是返回true,否则返回false
size()返回队列中有效元素的个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾将元素val入队列
pop()将队头元素出队列

🍒 🍒模拟实现⬇️ ⬇️:

#include<iostream>
#include<deque>

using std::cin;
using std::cout;
using std::endl;
using std::deque;

namespace lz
{
	template<class T, class Container = deque<T>>
	class queue
	{
	private:
		Container _con;

	public:
		queue()
			:_con()
		{}

		//插入删除
		void push(const T& val) { _con.push_back(val); }
		void pop() {if (empty())return; _con.pop_front();}

		//数据元素,判空
		size_t size() { return _con.size(); }
		bool empty() { return _con.size() == 0; }

		//获得队头和队尾元素
		T& front() { return _con.front(); }
		const T& front()const { return _con.front(); }
		//T& back() { return _con.back; }
		//const T& back()const { return _con.back; }
	};
}

#include"queue.h"

void Test_queue()
{
	lz::queue<int> q1;
	q1.push(1);
	q1.push(2);
	q1.push(3);
	q1.push(4);

	while (!q1.empty())
	{
		cout << q1.front() << endl;
		q1.pop();
	}
	cout << q1.size() << endl;
}

int main()
{
	//Test_stack();
	Test_queue();
	return 0;
}

注意❗️ ❗️



三、 priority_queue

🌳1、概念

🍉 🍉如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。这样,我们就引入了优先级队列这种数据结构。

🌹 🌹 优先级队列(priority queue): 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素 (3)删除 一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。

注意❗️ ❗️

🌳 2、用法

🌵🌵常用接口:

constructor(构造函数)用法
priority_queue()空的优先级队列
priority_queue(Iterator first, Iterator last)迭代器区间进行构造
函数用法
empty判断优先级队列是否为空
size计算队列中元素个数
top取队列中优先级最高的元素(队头元素)
push从队尾插入元素
pop删除优先级最高的元素(队头的元素)

🌳3、模拟实现

🍒 🍒这里我们来实现一个简易的priority_queue⬇️ ⬇️:

#include<iostream>
#include<vector>

using std::cin;
using std::cout;
using std::endl;


namespace lz
{
	//仿函数
	template<class T>
	struct less
	{
		bool operator()(const T& left, const T& right)
		{
			return left < right;
		}
	};

	template<class T>
	struct greater
	{
		bool operator()(const T& left, const T& right)
		{	
			return left > right;
		}
	};


	//优先队列
	template
		<class T,class Container = std::vector<T>,class Compare = less<T>>
	class priority_queue
	{
	public:
		Compare Com;
		priority_queue()
			:_con()
		{}

		template<class Iterator>
		priority_queue(Iterator first, Iterator last)
			:_con(first, last)
		{
			int parent = (size() - 2) >> 1;
			for(int i = parent; i >= 0 ; i--)
				adjust_down(i);
		}

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

		//队头出队
		void pop() 
		{ 
			if (!empty())
			{
				std::swap(_con.front(), _con.back());
				_con.pop_back();
				adjust_down(0);
			}
			//因为部分的容器不提供头删,所以我们通过交换后进行删除
			//不建议使用erase
		}

		//容量
		size_t size()const { return _con.size(); }

		//返回队头元素
		const T& top()const { return _con.front(); }

		//判空
		bool empty()const { return _con.empty(); }


	private:

		//向下调整法
		void adjust_down(int parent)
		{
			int child = parent * 2 + 1;
			while (child < size())
			{
				if (child + 1 < size() && Com(_con[child] , _con[child + 1]))
				{
					child++;
				}
				if (Com(_con[parent] , _con[child]))
				{
					std::swap(_con[parent], _con[child]);
						parent = child;
						child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

		//向上调整法
		void adjust_up(int child)
		{
			int parent = (child - 1) >> 1;
			while (child)
			{
				if (Com(_con[parent] , _con[child]))
				{
					std::swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) >> 1;
				}
				else
				{
					break;
				}
			}

		}

		Container _con;
	};
}



#include"priority_queue.h"

void Test1()
{
	lz::priority_queue<int, std::vector<int>, lz::less<int>> pq1;
	pq1.push(1);
	pq1.push(2);
	pq1.push(3);
	pq1.push(4);
	pq1.push(5);
	pq1.push(6);

	while (!pq1.empty())
	{
		cout << pq1.top() << " ";
		pq1.pop();
	}
	cout << endl;

	std::vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(9);
	v1.push_back(8);

	lz::priority_queue<int, std::vector<int>, lz::greater<int>> 
		pq(v1.begin(), v1.end());

	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	
}

int main()
{
	Test1();

	return 0;
}

注意❗️ ❗️


😎 😎今天的内容到这里就结束了,我们下期再见!
在这里插入图片描述

举报

相关推荐

0 条评论