优先级队列

 优先级队列是用vector适配的容器适配器。

优先级队列是优先级高的先出队列。底层是堆。

每个父亲大于孩子是大堆,小于孩子是小堆。

用vector就理所应当了。

那么能用什么替代vector?

可以用deque。 但是没有vector好。

优先级队列头文件是queue。

默认是大数优先级高。它默认是个大堆。

划线部分是less的话默认是大堆。是大数优先级高。

 less和great的头文件是functional。

215. 数组中的第K个最大元素 - 力扣(Leetcode)

两种方法。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int> qu(nums.begin(),nums.end());
        while(--k)
        qu.pop();
        return qu.top();
    }
};
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int,vector<int>,greater<int>> qu(nums.begin(),nums.begin()+k);
        for(int i=k;i<nums.size();i++)
        {
            if(nums[i]>qu.top())
            {
                qu.pop();
                qu.push(nums[i]);
            }
        }
        return qu.top();
    }
};

仿函数

namespace bit
{
	template<class T>
	class less
	{
	public:
		bool operator()(const T& x, const T& y) const
		{
			return x < y;
		}
	};

	template<class T>
	class greater
	{
    public:
		bool operator()(const T& x, const T& y) const
		{
			return x > y;
		}
	};
}
int main()
{
bit::less LessFun;
LessFun(1,2);
return 0;
}

这个仿函数有什么用?

举个例子。c语言中,如果我们用冒泡排序,想随时更改这个函数是拍升序还是降序,需要通过在冒泡排序函数参数传一个函数指针来实现。

用仿函数进行更改。 

 

 

 这也是之前优先级队列less表示大堆的原因。

第三个参数虽然有对象的拷贝,,但这个对象因为只有一个成员函数,成员函数不占字节,所以这个对象只有一个字节,拷贝不会有太大影响。

 传匿名对象也可以。

改成引用的话,形参需要定义为const,类中的成员函数也需要定义为const。

 

 


利用仿函数模拟实现优先级队列。

template<class T, class Container = vector<T>, class Compare = less<T>>
	class priority_queue
	{
	public:
		priority_queue()
		{}

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

		void adjust_up(size_t child)
		{
			Compare com;
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[parent] < con[child])
				if (com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void push(const T& x)
		{
			_con.push_back(x);

			adjust_up(_con.size() - 1);
		}

		void adjust_down(size_t parent)
		{
			Compare com;
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				//if (child+1 < _con.size() && _con[child] < _con[child+1])
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					child++;
				}

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

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

			adjust_down(0);
		}

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

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

		size_t size() const
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}
int main()
{
	//bit::priority_queue<int> pq; // < // 大堆
	bit::priority_queue<int, vector<int>, greater<int>> pq; // >  // 小堆
	pq.push(3);
	pq.push(1);
	pq.push(2);
    pq.push(5);

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

而如果我们传Date日期类的地址,我们发现,它会按地址进行比较,而每次运行,new出来的地址都不同,因此每次优先级排序都不同。

 第一次结果

 第二次结果

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}

	bool operator<(const Date& d)const
	{
		return (_year < d._year) ||
			(_year == d._year && _month < d._month) ||
			(_year == d._year && _month == d._month && _day < d._day);
	}

	bool operator>(const Date& d)const
	{
		return (_year > d._year) ||
			(_year == d._year && _month > d._month) ||
			(_year == d._year && _month == d._month && _day > d._day);
	}

	friend ostream& operator<<(ostream& _cout, const Date& d)
	{
		_cout << d._year << "-" << d._month << "-" << d._day;
		return _cout;
	}

private:
	int _year;
	int _month;
	int _day;
};

那么我们怎么能解决这个问题呢?

我们可以再创建一个通过比较日期大小的greater和less。 

struct PDateLess
{
	bool operator()(const Date* d1, const Date* d2)
	{
		return *d1 < *d2;
	}
};

struct PDateGreater
{
	bool operator()(const Date* d1, const Date* d2)
	{
		return *d1 > *d2;
	}
};
priority_queue<Date*, vector<Date*>, PDateLess> q3;
	q3.push(new Date(2018, 10, 29));
	q3.push(new Date(2018, 10, 28));
	q3.push(new Date(2018, 10, 30));
	cout << *q3.top() << endl;

	// 小堆
	priority_queue<Date*, vector<Date*>, PDateGreater> q4;
	q4.push(new Date(2018, 10, 29));
	q4.push(new Date(2018, 10, 28));
	q4.push(new Date(2018, 10, 30));
	cout << *q4.top() << endl;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南种北李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值