[STL]优先级队列的模拟实现(堆)

本文详细介绍了C++中优先级队列的调整算法(向上调整和向下调整)及其在大堆和小堆转换中的使用,以及通过拟函数重载操作符实现动态改变优先级的模板方法。
摘要由CSDN通过智能技术生成

        优先级队列的基本操作实现时:需要两个重要的调整:向上调整算法(Adjust_up),向下调整算法(Adjust_down)。初次之外,还有一个拟函数的重要思想和实现操作来帮助我们实现大堆和小堆的转换。

基础框架:(这里我们同样采用适配器的写法)

template<class T, class Container=vector<T>,class Compare = less<T> >
	class priority_queue
	{
        public:
        void Adjust_up();
        void Adjust_down();
        void push(const T &x);
        void pop();
        const T& top();
        int size();
        bool empty();
        private:
        Container _con;
    }
​

​

那么我们先来看这两种算法(前面的堆相关文章有详细解说,即此处只呈现代码): 

1.向上调整算法:

void Adjust_up(int child)
		{
			int parent = (child-1) / 2;
			while (child > 0)
			{	
				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
				
			}
		}	

2.向下调整算法:

void Adjust_down(int parent)
		{
			int child = parent * 2 + 1;
			while (child < _con.size())
			{

				if (child + 1 < _con.size() && _con[child] < _con[child + 1])
					child++;
			  if (_con[child] > _con[parent])
				{
				swap(_con[child], _con[parent]);
				parent=child;
				child = parent * 2+1;   
				}
			else
			break;
			
			}
		}

拟函数:

作用: 简单来说,就是可以把 类的对象 用函数的方式使用,也就是模拟函数的使用。

其实质上是利用类对( )操作符的重载:

         ls(a,b)模拟函数名加传参的操作,但实际上是一个对象调用了运算符函数。所以我们再利用模板就可以实现对优先级队列中优先级进行随时的更改(就是这个优先级队列是大堆还是小堆)。

        所以,我们又有知道模板可以传一个容器,或者自定义的类型:

因此,最终呈现的优先级队列模拟的代码也要因此修改:(主要是修改两个重要调整算法里面的比较):

template<class T>
	struct less
	{
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};
	template<class T>
	struct greater
	{
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};

	template<class T, class Container=vector<T>,class Compare = less<T>>
	class priority_queue
	{
	public:
	void Adjust_up(int child)
		{
		Compare com;
			int parent = (child-1) / 2;
			while (child > 0)
			{	
				//if (_con[child] > _con[parent])
				if (com(_con[parent],_con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
				
			}
		}	
		void Adjust_down(int parent)
		{
			Compare com;
			int child = parent * 2 + 1;
			while (child < _con.size())
			{

				if (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 push(const T& x)
		{
			_con.push_back(x);
			Adjust_up(_con.size() - 1);
		}
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			Adjust_down(0);
		}

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

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


	private:
		Container _con;
	};

        以上就是优先级队列实现的重点,掌握之后就能轻松实现了,小伙伴们学会了吗?如有不妥的地方,请小伙伴们指正哦~,下次再见。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值