堆实现优先队列

堆实现

为什么要使用堆实现优先队列?
在前面讲了用链队实现优先队列,其思想是插入元素时按普通队列入队,在删除元素(出队)时按优先队列的性质删除.那么就还有一种方式,即插入元素时按优先队列的方式插入,删除时按普通顺序队列的方式删除.那就是用堆实现优先队列!

由于前面已经写过堆的实现,这里不再重复造轮子,读者可以自己改写实现优先队列,我们使用容器适配器.堆的实现

首先我们需要一个容器,vector容器能满足这个需求.vector容器可以看作一个变长数组,可随时增大减小.
使用方法:vector<类型> 标识符

需要用到的方法:
void push_back(const T& x):向量尾部增加一个元素X
void pop_back():删除向量中最后一个元素
iterator begin():返回向量头指针,指向第一个元素
iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置

按最大堆将vector容器中的元素重新组织顺序,需要用到的方法:
make_heap (_RAIter , _RAIter)以堆的形式对容器元素排序,默认生成最大堆.实际上,第一个和第二个参数是迭代器,请看下图:
在这里插入图片描述
这是make_heap的两个重载函数,第二个在下面马上讲到.第一行是模板,里面的RandomAccessItarator是随机存取迭代器的意思.

迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址.

如果不太理解,会用就行了,上面vector容器的操作中begin()和end()正好提供了这两个参数,前者返回第一个元素的迭代器,后者返回最后一个元素的后一个位置的迭代器.

make_heap(_RAIter ,_RAIter,_Compare)_Compare可以自定义,也可以用已经实现的.生成最小堆:greater<>(),生成最大堆less<>(),如果要使用,请加头文件<fuctional>.让一个函数既能接受函数指针,又能接受函数对象,其中一种方法就是使用模板,所以这里的comp参数可以是函数指针,也可以是函数对象,排序的原则:如果第一个参数排在第二个参数前面,返回false,否则返回true.
这里贴出默认的最大堆的代码,可以从中看出排序的原则:

template<>
	struct less<void>
	{	// transparent functor for operator<
	typedef int is_transparent;

	template<class _Ty1,
		class _Ty2>
		constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
		-> decltype(static_cast<_Ty1&&>(_Left)
			< static_cast<_Ty2&&>(_Right))
		{	// transparently apply operator< to operands
		return (static_cast<_Ty1&&>(_Left)
			< static_cast<_Ty2&&>(_Right));//如果第一个参数排在第二个参数前面,返回false,否则返回true.
		}
	};

如果希望以自定义结构体中某个变量的权重为标准进行最大堆排序,那么就要自定义,这里我们自定义.

push_heap(_RAIter,_RAIter)将第一个元素与最后一个元素交换,然后使交换后(除最后一个元素)仍具有堆的性质,默认为最大堆.
push_heap(_RAIter,_RAIter,_Compare)这里的_Compare同上.
特别注意:如果make_heap()中用的是自己的比较函数,那么pop_heap()的第3个参数也需要是这个函数!

全部代码及测试代码

思路已经在代码中以注释的方式显示.

#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>

using namespace std;

typedef struct FHeap{
	int data;
	int priority;
}FHeap;

bool myCompare(FHeap* a, FHeap* b) {//以FHeap中的priority的大小为依据排序,生成最大堆
	return a->priority < b->priority;
}

int main(void) {
	vector<FHeap*> h;

	int n;
	cout << "请输入插入元素的个数:";
	cin >> n;
	while (n--) {
		FHeap* e=new FHeap;
		cout << "请输入插入的元素:";
		cin >> e->data;
		cout << "请输入优先级:";
		cin >> e->priority;

		h.push_back(e);//插入元素至末尾
	}
	make_heap(begin(h), end(h), myCompare);//排序

	for (unsigned int i = 0; i < h.size(); i++) {
		cout << "数据:" << h[i]->data << "\t" << "优先级:" << h[i]->priority << endl;
	}

	pop_heap(begin(h), end(h), myCompare);//准备出队,优先级最高的移至队尾
	cout << "出队元素的数据:" << h[h.size() - 1]->data << endl;//打印容器中最后一个元素的数据
	h.pop_back();//出队(删除最后一个元素)

	system("pause");
	return 0;
}

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值