STL源码解析 - sort_heap

 模板函数sort_heap具有如下两个版本

template<class _RanIt>
void sort_heap(_RanIt _First, _RanIt _Last);

template<class _RanIt, class _Pr>
void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred);

其功能是完成区间 [_First, _Last) 内元素的堆排序,第一个版本采用小于操作符(operator<),

第二个版本采用一个二元谓词(binary predicate)。

下面将以第一个版本的算法源代码进行注释说明

template<class _RanIt> inline
	void sort_heap(_RanIt _First, _RanIt _Last)
	{	// order heap by repeatedly popping, using operator<
	_DEBUG_HEAP(_First, _Last);
	// 通过重复取出第一个元素完成堆排序
	_Sort_heap(_CHECKED_BASE(_First), _CHECKED_BASE(_Last));
	}

_Sort_heap函数

template<class _RanIt> inline
	void _Sort_heap(_RanIt _First, _RanIt _Last)
	{	// order heap by repeatedly popping, using operator<
	_DEBUG_RANGE(_First, _Last);
	_DEBUG_HEAP(_First, _Last);
	// 通过重复取出第一个元素完成堆排序
	for (; 1 < _Last - _First; --_Last)
		std::pop_heap(_First, _Last);
	}

pop_heap函数

template<class _RanIt> inline
	void pop_heap(_RanIt _First, _RanIt _Last)
	{	// pop *_First to *(_Last - 1) and reheap, using operator<
	_DEBUG_RANGE(_First, _Last);
	_DEBUG_HEAP(_First, _Last);
	if (1 < _Last - _First) // 将第一个元素放在末尾
		_Pop_heap_0(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Val_type(_First));
	}

_Pop_heap_0函数

template<class _RanIt,
	class _Ty> inline
	void _Pop_heap_0(_RanIt _First, _RanIt _Last, _Ty *)
	{	// pop *_First to *(_Last - 1) and reheap, using operator<
	// 将第一个元素放在末尾,注意这里将原末尾元素以参数值传递形式传入
	_Pop_heap(_First, _Last - 1, _Last - 1,
		_Ty(*(_Last - 1)), _Dist_type(_First));
	}


_Pop_heap函数

template<class _RanIt,
	class _Diff,
	class _Ty> inline
	void _Pop_heap(_RanIt _First, _RanIt _Last, _RanIt _Dest,
		_Ty _Val, _Diff *)
	{	// pop *_First to *_Dest and reheap, using operator<
	// 更新末值
	*_Dest = *_First;
	// 对末值前的区间元素进行堆调整,_Val 为原末值
	std::_Adjust_heap(_First, _Diff(0), _Diff(_Last - _First), _Val);
	}

_Adjust_heap函数

template<class _RanIt,
	class _Diff,
	class _Ty> inline
	void _Adjust_heap(_RanIt _First, _Diff _Hole, _Diff _Bottom, _Ty _Val)
	{	// percolate _Hole to _Bottom, then push _Val, using operator<
	_Diff _Top = _Hole;
	_Diff _Idx = 2 * _Hole + 2;

	for (; _Idx < _Bottom; _Idx = 2 * _Idx + 2)
		{	// move _Hole down to larger child
		// 求取左右孩子中的值较大者
		if (_DEBUG_LT(*(_First + _Idx), *(_First + (_Idx - 1))))
			--_Idx;
		// 这里使用了逗号表达式
		*(_First + _Hole) = *(_First + _Idx), _Hole = _Idx;
		}

	if (_Idx == _Bottom)
		{	// only child at bottom, move _Hole down to it
		*(_First + _Hole) = *(_First + (_Bottom - 1));
		_Hole = _Bottom - 1;
		}
	std::_Push_heap(_First, _Hole, _Top, _Val);
	}


_Push_heap函数

template<class _RanIt,
	class _Diff,
	class _Ty> inline
	void _Push_heap(_RanIt _First, _Diff _Hole,
		_Diff _Top, _Ty _Val)
	{	// percolate _Hole to _Top or where _Val belongs, using operator<
	// 将给定值 _Val 放入正确的节点中
	for (_Diff _Idx = (_Hole - 1) / 2;
		_Top < _Hole && _DEBUG_LT(*(_First + _Idx), _Val);
		_Idx = (_Hole - 1) / 2)
		{	// move _Hole up to parent
		// 当前节点值小于 _Val,则上溯
		*(_First + _Hole) = *(_First + _Idx);
		_Hole = _Idx;
		}
         // 找到不小于 _Val 的节点
	*(_First + _Hole) = _Val;	// drop _Val into final hole
	}

至此已完成堆排序,不过使用sort_heap需要注意下面三点

(1)首先把建堆,即调用make_heap

(2)由于对原末值的保存是通过参数值传递,如_Pop_heap及以后的函数中的参数 _Val,因而对于某些复杂的自定义类型将不适用,

即expensive type
(3)sort_heap的时间复杂度为O(NlogN)

 代码版本来源于Microsoft Visual Studio 2008 安装包中<algorithm>文件,版权归原作者所有!

你可能感兴趣的:(Algorithm,算法,Microsoft,Class,UP)