堆(heap)的操作c++

堆的操作:


堆的操作函数定义在头文件 algorithm 中

以下的代码中均省略了输出的代码

vector<int> a{ 4,5,6,7,3,0,1 };
for (int i = 0; i < a.size(); i++)
	{
		cout << a[i] << ' ';
	}

创建堆:堆用容器vector来存放

函数:make_heap()根据指定的迭代器区间以及一个可选的比较函数,来创建一个heap,默认创建大根堆

// 1
template< class RandomIt >
void make_heap( RandomIt first, RandomIt last );

// 2
template< class RandomIt, class Compare >
void make_heap( RandomIt first, RandomIt last, Compare comp );

vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end());

输出堆a:
在这里插入图片描述


指定比较函数创建大根堆:

make_heap(a.begin(), a.end(),less<int>());

在这里插入图片描述

指定比较函数创建小根堆:

make_heap(a.begin(), a.end(),greater<int>());

在这里插入图片描述


插入堆:

函数:push_heap()把指定区间的最后一个元素插入到heap中
注:在使用之前要想vector末尾中插入元素

// 1
template< class RandomIt >
void push_heap( RandomIt first, RandomIt last );

// 2
template< class RandomIt, class Compare >
void push_heap( RandomIt first, RandomIt last, Compare comp );


先用make_heap来构造一个堆,然后在容器末尾追加元素之后,把新的迭代器区间传给push_heap,这样新尾部元素也被添加到堆中。

vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end(),less<int>());
a.push_back(100);
push_heap(a.begin(), a.end());

结果:
在这里插入图片描述
默认使用的是大根堆的比较方式

注意:使用push_heap(f, l)的话,调用者需要确保(f, l-1)已经是一个堆. push_heap(f, l)仅仅会把*(l)插入到(f, l-1)这个区间形成的堆中

若使用的是不同的比较函数:

vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end(),less<int>());
a.push_back(100);
push_heap(a.begin(), a.end(),greater<int>());

在这里插入图片描述
100在插入堆使用的是小根堆的比较方式,而他的父节点4比100小,且4-3-100所形成的堆中已经是小根堆,所以就不进行替换。


弹出堆:

函数:pop_heap()弹出heap顶元素, 将其放置于区间末尾

// 1
template< class RandomIt >
void pop_heap( RandomIt first, RandomIt last );

// 2
template< class RandomIt, class Compare >
void pop_heap( RandomIt first, RandomIt last, Compare comp );

它的作用是:交换first和*(last-1), 然后把(first, last-1)建成一个max(min) heap. 也就是说把堆顶的最大元素交换到区间尾,然后把除了尾部的元素的剩余区间重新调整成堆。

vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end(),less<int>());
pop_heap(a.begin(), a.end());
int max = a.back();
a.pop_back();

在这里插入图片描述
注意的是,调用者要保证,在调用pop_heap时(first, last)已经是一个堆(使用相同的排序准则)。


堆排序:

函数:sort_heap()堆排序算法,通常通过反复调用pop_heap来实现
是经典的堆排序算法,通过每次弹出堆顶直到堆为空,依次被弹出的元素就组成了有序的序列了

// 1
template< class RandomIt >
void sort_heap( RandomIt first, RandomIt last );

// 2
template< class RandomIt, class Compare >
void sort_heap( RandomIt first, RandomIt last, Compare comp );

vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end(),less<int>());
sort_heap(a.begin(), a.end());

在这里插入图片描述
使用sort_heap(f, l)处理过的区间因为已经有序,就不再是一个最大堆或者是最小堆了。


判断堆:

函数:is_heap()判断给定区间是否是一个最大堆或者最小堆//是返回1,不是返回0
//1 (since C++11)
template< class RandomIt >
bool is_heap( RandomIt first, RandomIt last );

//2 (since C++11)
template< class RandomIt, class Compare >
bool is_heap( RandomIt first, RandomIt last, Compare comp );

	vector<int> a{ 4,5,6,7,3,0,1 };
	bool flag = is_heap(a.begin(), a.end());
	cout << "before heap a:";
	if (flag)
		cout << "此时堆是一个最大堆或者最小堆" << endl;
	else cout << "此时堆不是一个最大堆或者最小堆" << endl;
	make_heap(a.begin(), a.end(),less<int>());
	flag = is_heap(a.begin(), a.end());
	cout << "after heap a:";
	if (flag)
		cout << "此时堆是一个最大堆或者最小堆" << endl;
	else cout << "此时堆不是一个最大堆或者最小堆" << endl;

在这里插入图片描述


判断堆并返回第一个不满足条件的位置:

函数:is_heap_until()

//1 (since C++11)
template< class RandomIt >
RandomIt is_heap_until( RandomIt first, RandomIt last );

//2 (since C++11)
template< class RandomIt, class Compare >
RandomIt is_heap_until( RandomIt first, RandomIt last, Compare comp );

vector<int> a{ 4,5,6,7,3,0,1 };
auto iter = is_heap_until(a.begin(), a.end());
cout << "iter:" << *iter << endl;

我们可以自己分析得到在3的位置就不满足小根堆的规律,在3之前的元素满足小根堆的规律,所以iter应该是5
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

陈乐乐happy

觉得对你有用的话可以打赏打赏

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

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

打赏作者

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

抵扣说明:

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

余额充值