/**
* @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_
堆排序的实现
最新推荐文章于 2024-12-30 20:13:45 发布