堆排序
堆排序: 通过将数组的元素转化成完全二叉树,并将完全二叉树转化为大顶堆(升序)或者小顶堆(降序),通过循环逐次获取最大值或最小值达到排序的目的。
思路
· 升序为例(大顶堆)
- 将数组转化成完全二叉树,其中最后一个非叶子节点的下标为 (数组长度/2-1),任意节点(非叶子节点)的左子树为2*i+1,右子树为2*i+2(i为数组下标)。
- 从最后一个非叶子节点往前遍历,将每个子树调整为大顶堆,最终实现整个树为大顶堆
- 将数组的首元素(最大值)与末尾元素交换,然后再将数组剩下的元素调整为大顶堆,交换首末元素,依次循环。
代码实现
void HeapSort(int *arr,int len)
{
for(int i=len/2-1;i>=0;i--)
{
//从最后一个非叶子节点向前遍历
HeapAdj(arr,len);//调整为大顶堆
}
//交换堆顶元素和最后一个元素
for(int i=len-1;i>=0;i--)
{
swap(arr,i,0);//交换数组两个索引处的值
HeapAdj(arr,0,i);//再次将二叉树调整为大顶堆获取最大值
}
}
· 调整大顶堆的辅助函数
@param arr 待调整的数组
@param index 待调整的结点的下标
@param len 数组的长度
void HeapAdj(int* arr,int index, int len)
{
int max=index;//将默认初始值的下标初始为最大值下标
int leftIndex=index*2+1;
int rightIndex=index*2+2;
if (leftIndex<len && arr[leftIndex]>arr[max])
{
max = leftIndex;
}
if (rightIndex<len && arr[rightIndex]>arr[max])
{
max = rightIndex;
}
if (max!=index)//如果max不等于index,交换
{
swap(arr, max, index);
//发生交换后max位置的节点与其左右子树之间大小可能不是大顶堆了。所以再次递归调整
HeapAdj(arr,max,len);
}
}