push_heap 源码剖析

一:用法示例

一共两个重载:

default (1)   
template <class RandomAccessIterator>
  void push_heap ( RandomAccessIterator first ,  RandomAccessIterator last ) ;
custom (2)   
template <class RandomAccessIterator, class Compare>
  void push_heap ( RandomAccessIterator first ,  RandomAccessIterator last , Compare comp ) ;

在说明这个函数的功能之前,我们先来看看对它的英文解释:

Push element into heap range
Given a heap in the range [first,last-1), this function extends the range considered a heap to [first,last) by placing the value in (last-1) into its corresponding location within it.

大概意思是,push_heap的作用范围是[ first , last),在使用push_heap必须保证[ first , last-1)满足堆,而*(last-1)是新增在末尾的一个值,那么此时对于整个[ first , last ) , 因为*(last-1)的新增可能已经不满足堆。push_back的作用就是重新调整*(last-1)的位置,使其整个[ first , last )满足堆。

例子:

#include<iostream>
#include<functional>
#include<algorithm>
#include<vector>

using namespace std;

int main()
{
	
	int a[10] = { 2,1,6,4,9,10,3,5,8,7 };
	vector<int> v(a, a + 10);
	sort(v.begin(), v.end());//现在是一个小顶堆

	v.push_back(-1);//现在在末尾插入一个-1,是整个数组的最小值

	push_heap(v.begin(), v.end(), greater<>());//现在-1已经在头部位置

	for (auto it = v.begin(); it != v.end(); it++)
		cout << *it << " ";//-1 1 3 4 2 6 7 8 9 10 5 
	cout << endl;

	return 0;
}


二:源码及剖析

源码方面的话,其实一点都不难,一共4个模板函数,重点是第一个,其余三个都是基于第一个模板函数的。

// TEMPLATE FUNCTION push_heap WITH PRED
template<class _RanIt,
	class _Diff,
	class _Ty,
	class _Pr> inline
	void _Push_heap(_RanIt _First, _Diff _Hole,
		_Diff _Top, _Ty&& _Val, _Pr _Pred)
	{	// percolate _Hole to _Top or where _Val belongs, using _Pred
	for (_Diff _Idx = (_Hole - 1) / 2;
		_Top < _Hole && _DEBUG_LT_PRED(_Pred, *(_First + _Idx), _Val);
		_Idx = (_Hole - 1) / 2)
		{	// move _Hole up to parent
		*(_First + _Hole) = _STD move(*(_First + _Idx));
		_Hole = _Idx;
		}
/*
_Top < _Hole是对边界的判断;
_DEBUG_LT_PRED(_Pred, *(_First + _Idx), _Val)相当于_Pred(*(_First + _Idx), _Val)
*/

	*(_First + _Hole) = _STD move(_Val);	// drop _Val into final hole
	}

template<class _RanIt,
	class _Diff,
	class _Ty,
	class _Pr> inline
	void _Push_heap_0(_RanIt _First, _RanIt _Last, _Pr _Pred, _Diff *, _Ty *)
	{	// push *_Last onto heap at [_First, _Last), using _Pred
	_Diff _Count = _Last - _First;
	if (0 < _Count)
		{	// worth doing, percolate *_Last
		_Ty _Val = _STD move(*_Last);
		_Push_heap(_First, _Count, _Diff(0), _STD move(_Val), _Pred);
		}
	}

template<class _RanIt,
	class _Pr> inline
	void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred)
	{	// push *(_Last - 1) onto heap at [_First, _Last - 1), using _Pred
	_DEBUG_RANGE_PTR(_First, _Last, _Pred);
	if (_First != _Last)
		{	// check and push to nontrivial heap
		--_Last;
		_DEBUG_HEAP_PRED(_First, _Last, _Pred);
		_Push_heap_0(_Unchecked(_First), _Unchecked(_Last), _Pred,
			_Dist_type(_First), _Val_type(_First));
		}
	}

		// TEMPLATE FUNCTION push_heap
template<class _RanIt> inline
	void push_heap(_RanIt _First, _RanIt _Last)
	{	// push *(_Last - 1) onto heap at [_First, _Last - 1), using operator<
	_STD push_heap(_First, _Last, less<>());
	}


源码摘抄自Visual Studio 2015安装目录algorithm文件中。



点击进入目录----> C++源码剖析目录










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值