堆排序的实现

/**
* @file BinaryHeap.hpp
* @brief 二叉堆
* 
* @author xiao2 joyjj0218@qq.com 
* @version 1.0 
* @date 2015.11.17 
*/


#ifndef BINARYHEAP_HPP_
#define BINARYHEAP_HPP_


#include <vector>
#include <algorithm>


using namespace std;


/**
* @brief 算法
*/
namespace algorithm
{
/**
* @brief 二叉堆模板类
*/
template <typename comparable>
class BinaryHeap
{
public:
	/**
	* @brief 二叉堆构造函数
	* @param[in] item 输入二叉堆的vector序列
	*/
	explicit BinaryHeap(vector<comparable> &item) :
	m_vecArray(item), m_iSize(m_vecArray.size())
	{
	}

public:
	/**
	* @brief 建立最小堆
	* @param[in] current_size 当前堆大小
	* @return void
	*/
	void BuildHeap(int current_size)
	{
		for(int i = current_size / 2 - 1 ; i >= 0; i--)  // 从最后一个叶子节点的父节点开始
			PercolateDown(i, current_size);  // 渗透下沉
	}

	/**
	* @brief 堆排序
	* @return void
	*/
	void HeapSort()
	{
		for(int i = m_iSize; i > 0; i--) {  // 从最后一个节点开始
			BuildHeap(i);  // 建立堆,堆的大小在删除堆顶元素后递减1
			swap(m_vecArray[0], m_vecArray[i-1]);  // 堆顶元素(最小值)与堆尾元素交换(即删除堆顶元素)
		}
	}

private:
	/**
	* @brief 渗透下沉
	* @param[in] current 当前下沉索引(索引从0开始)
	* @param[in] current_size 当前下沉序列大小
	* @return void
	*/
	void PercolateDown(int current, int current_size)
	{
		int parent;
		int child;

		parent = current;  // 当前下沉位置作为父节点
		comparable temp = m_vecArray[current];  // 保存下沉初始值

		for( ; (2 * parent + 1) < current_size; ) {  // 左子节点索引小于当前下沉序列大小
			child = 2 * parent + 1;  // 左子节点索引

			if(child < current_size - 1 && m_vecArray[child+1] < m_vecArray[child])  // 如果有右子节点(即左子节点兄弟节点)且右子节点小于左子节点
				child++;  // 右子节点索引

			if(m_vecArray[child] < temp) {  // 如果左(右)子节点小于父节点
				m_vecArray[parent] = m_vecArray[child];  // 较小的子节点替换父节点
				parent = child;  // 父节点下沉到较小的子节点
			} else {
				break;  // 满足二叉堆性质,退出
			}
		}
		m_vecArray[parent] = temp;  // 下沉初始值填充最后一个替换节点
	}

private:
	vector<comparable> &m_vecArray;  ///< 输入vector数组的引用(索引从0开始)
	int m_iSize;  ///< vector数组的大小
};
}


#endif  // BINARYHEAP_HPP_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值