1. 主要思想
堆排序顾名思义使用堆(二叉堆)数据结构实现排序。实现升序排列需要使用最大堆(二叉最大堆),实现降序排列使用最小堆(二叉最小堆)。
堆排序的实现:(以升序最大堆为例)
- 维护当前节点满足最大堆属性(父节点 >= 子节点)。
- 从下而上维护当前节点属性为最大堆属性,便构建了一个最大堆。
- 移除(移动至队尾)最大堆中的根节点(最大节点),将剩余节点构建最大堆,依次完成。
- 堆排序完成。
2. 维护最大堆
说明:
- 数组二叉树的根节点索引为0,双亲索引为index时,则其左孩子索引为index2+1,其右孩子索引为index2+2。
//递归先右后左维护最大堆属性
void maxHeapify(vector<int>& nums, int index, int heapSize)
{
int left = index*2+1;
int right = index*2+2;
int maxIndex = index;
if( left < heapSize && nums[maxIndex] < nums[left] )
maxIndex = left;
if( right < heapSize && nums[maxIndex] < nums[right] )
maxIndex = right;
if(maxIndex != index)
{
swap(nums[index], nums[maxIndex]);
maxHeapify(nums, maxIndex, heapSize);
}
}
3.构建最大堆
说明:
- 初始值为heapSize/2,而索引为heapSize/2+1, heapSize/2+2, ···, heapSize时都为叶结点。
- 构建后的根结点值最大。
//从下而上构造最大堆
void buildMaxHeapify(vector<int>& nums, int heapSize)
{
for(int i=heapSize/2; i>=0 ; i--)
{
maxHeapify(nums, i, heapSize);
}
}
4. 实现堆排序
void heapSort(vector<int>& nums)
{
int heapSize = nums.size();
buildMaxHeapify(nums, heapSize);
//swap将每次排序后的最大值放置到当前队尾,形成从小到大排序
for(int i=nums.size()-1; i>=1; i--)
{
swap(nums[0], nums[i]);
heapSize--;
maxHeapify(nums, 0, heapSize);
}
}