【C++初阶】:优先队列(仿函数)

优先队列

  • 一.基本使用
  • 二.模拟实现
  • 三.仿函数
    • 1.优先队列里的使用
    • 2.概念
    • 3.模拟

一.基本使用

优先队列的底层默认是使用vector构造的,也就是使用数组模拟(二叉树)堆。并且默认是按大堆存放数据(也就是父节点>子节点,左节点>右节点)。

【C++初阶】:优先队列(仿函数)_第1张图片

优先队列的成员函数不多,常用的就是empty,size,top,pop,push。

【C++初阶】:优先队列(仿函数)_第2张图片

简单使用

首先优先队列常使用区间初始化和无参初始化。

【C++初阶】:优先队列(仿函数)_第3张图片

可以使用push插入数据,注意因为优先队列是使用数组模拟堆,所以不能直接遍历。只能通过不断访问顶部数据,再不断弹出顶部数据进行间接遍历。

【C++初阶】:优先队列(仿函数)_第4张图片

【C++初阶】:优先队列(仿函数)_第5张图片

二.模拟实现

这里使用了模板参数(template),一共有两个参数,第一个T用来适配不同类型的数据(例如int,string或者自定义类型),第二个参数默认是vector,也就是底层默认是用vector实现优先队列,当然也可以使用list等等(这里与库里保持一致)。

#include

namespace mine
{
	template<class T,class Container=vector<T>>
	class priority_queue
	{
	private:
		//向下调整
		void AdjustDown(int parent)
		{
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() &&  _con[child]< _con[child + 1])
				{
					child++;
				}
				if (_con[parent]<_con[child])
				{
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}	
			}
		}

		//向上调整
		void AdjustUp(int child)
		{
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[parent] <_con[child])
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
	public:
		//无参构造
		priority_queue()
		{}
		//区间构造
		template<class InputLterater>
		priority_queue(InputLterater first,InputLterater last)
		{
			while (first != last)
			{
				_con.push_back(*first);
				first++;
			}

			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				AdjustDown(i);
			}
		}
		//弹出顶部数据
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}
		//插入数据
		void push(const T&x)
		{
			_con.push_back(x);
			AdjustUp(_con.size() - 1);
		}
		//访问顶部数据
		const T& top()
		{
			return _con[0];
		}
		//数组大小
		size_t size()
		{
			return _con.size();
		}
		//是否为空
		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};

}

测试

#include
using namespace std;

#include"priority_queue.h"


int main()
{
	int a[9] = { 4,8,1,9,6,7,2,5,5};
	mine::priority_queue<int> v(a,a+9);//使用区间初始化


	mine::priority_queue<int> vv;//无参初始化
	vv.push(5);
	vv.push(2);
	vv.push(7);
	vv.push(11);
	while (!vv.empty())
	{
		cout << vv.top() << ' ';
		vv.pop();
	}
	return 0;
}

三.仿函数

1.优先队列里的使用

在库里除了T,Container两个模板参数外,还有一个Compare参数,这是一个仿函数用来改变存储顺序(默认是less,也就是大堆,可以改成greater,也就是小堆)

【C++初阶】:优先队列(仿函数)_第6张图片

【C++初阶】:优先队列(仿函数)_第7张图片

【C++初阶】:优先队列(仿函数)_第8张图片

【C++初阶】:优先队列(仿函数)_第9张图片

在这里插入图片描述

2.概念

仿函数的底层实际很简单,就是一个类里面重载了一个括号()运算符。

【C++初阶】:优先队列(仿函数)_第10张图片

在这里插入图片描述

仿函数的本质就是一个类的对象可以像函数一样使用。

3.模拟

由于less,greater本质都是类,库里有实现,所以就可以直接使用。

#include

namespace mine
{
	template<class T,class Container=vector<T>,class Compare=less<T>>
	class priority_queue
	{
	private:
		//向下调整
		void AdjustDown(int parent)
		{
			Compare com;
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (com(child + 1, _con.size()) && 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 AdjustUp(int child)
		{
			Compare com;
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				if (com(_con[parent],_con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
	public:
		//无参构造
		priority_queue()
		{}
		//区间构造
		template<class InputLterater>
		priority_queue(InputLterater first,InputLterater last)
		{
			while (first != last)
			{
				_con.push_back(*first);
				first++;
			}

			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				AdjustDown(i);
			}
		}
		//弹出顶部数据
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}
		//插入数据
		void push(const T&x)
		{
			_con.push_back(x);
			AdjustUp(_con.size() - 1);
		}
		//访问顶部数据
		const T& top()
		{
			return _con[0];
		}
		//数组大小
		size_t size()
		{
			return _con.size();
		}
		//是否为空
		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};

}

你可能感兴趣的:(C++初阶,c++,开发语言)