《STL仿函数》priority_queue模拟实现

一、priority_queue介绍

翻译priority_queue就是优先级队列,本质其实就是一个堆,不传仿函数的情况下,默认是个大堆。

二、priority_queue的模拟实现

template>
	class priority_queue
	{
	public:
		void adjust_up(int child)
		{
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[parent] < _con[child])
				{
					::swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(int parent)
		{
			int n = size();
			int child = parent * 2 + 1;
			while (child < n)
			{
				if (child + 1 < n && _con[child] < _con[child + 1])
				{
					child++;
				}
				if (_con[parent] < _con[child])
				{
					::swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

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

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

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

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

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

	private:
		Container _con;
	};

关于实现,会写堆的向上和向下调整算法就很容易,由于之前写过相关的文章,这里就不过多的介绍了,

《数据结构初阶》二叉树之堆的实现和堆排序_李逢溪的博客-CSDN博客

《数据结构初阶》堆排序总结与思考_李逢溪的博客-CSDN博客_堆排序实验总结

接下来,我们的主要问题围绕:priority_queue是一个堆,默认是一个大堆,如何实现一个通用的模板,我们传一个less类型,就能够生成一个大堆,传一个greater类型,就能够生成一个小堆。这里就需要我们学习仿函数,本质仿函数是一种设计模式,什么是设计模式?就是写代码的经验,前人总结出来的写代码的方式。

三、仿函数

仿函数本质上就是一个重载了operator()的类,由该类创建的对象可以像函数一样使用(),因此也被称作函数对象。

以下就是一个仿函数的简单使用:

template
class Less
{
public:
	bool operator()(const T& a, const T& b)
	{
		return a < b;
	}
};

int main()
{
	Less ls;
	cout << ls(3, 4) << endl;
	return 0;
}

less创建的对象ls,可以像函数一样使用ls(3,4),这就是一种仿函数的使用。

那么回到priority,如何写一个能够实例化出大堆和小堆的通用模板,这需要增加一个模板类型,然后由该类型创建一个对象,然后可以使用该对象实现child和parent<和>的比较。

template
	class Greater
	{
	public:
		bool operator()(const T& a, const T& b)
		{
			return a > b;
		}
	};


	template
	class Less
	{
	public:
		bool operator()(const T& a, const T& b)
		{
			return a < b;
		}
	};

	template, class Compare = Less>
	class priority_queue
	{
	public:
		void adjust_up(int child)
		{
			Compare cmp;
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[parent] < _con[child])
				if (cmp(_con[parent], _con[child]))
				{
					::swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(int parent)
		{
			Compare cmp;

			int n = size();
			int child = parent * 2 + 1;
			while (child < n)
			{
				//if (child + 1 < n && _con[child] < _con[child + 1])
				if (child + 1 < n && cmp(_con[child], _con[child + 1]))
				{
					child++;
				}

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

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

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

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

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

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

	private:
		Container _con;
	};

调用部分:

《STL仿函数》priority_queue模拟实现_第1张图片 

《STL仿函数》priority_queue模拟实现_第2张图片

 

你可能感兴趣的:(c++,c++)