假设数组索引从0开始计数:
- 对于任意位置i上的元素,其左子节点的索引为2i + 1,右子节点的索引为2i + 2。
- 对于任意位置i上的元素,其父节点的索引为(i -1) / 2(向下取整)
10
/ \
5 7
/ \ /
2 3 6
数组 a[i] 10 5 7 2 3 6
5的索引是 1 父节点(1 - 1)/ 2 = 0 左节点2x1+1 = 3
排序
1.建立最大堆:
在建立最大堆的过程中,堆的性质会被满足,即每个节点都比其子节点大(对于最大堆而言)。
确保堆顶元素为最大值。
2.交换堆顶元素与最后一个元素:
堆顶元素是最大值,将其与最后一个元素交换,相当于将当前最大值放到了已排序部分的末尾。此时最大值为有序序列。
调整堆:不断重复,下次调整不算最后的有序序列
交换之后,堆的性质可能被破坏,因为新的堆顶元素不一定是最大的了。因此,需要进行堆调整操作,将剩余元素重新构成一个最大堆。
#include<iostream>
using namespace std;
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// 维护最大堆
void max_heapify(int arr[], int len, int i)
{
int max = i;
int lson = 2 * i + 1;
int rson = 2 * i + 2;
if (lson < len && arr[max] < arr[lson])
{
max = lson;
}
if (rson < len && arr[max] < arr[rson])
{
max = rson;
}
if (max != i)
{
swap(arr[max], arr[i]);
max_heapify(arr, len, max);
}
}
void HeapSort(int arr[], int len)
{
// 建立最大堆
for (int i = (len -1)/2; i >= 0; i--)
{
max_heapify(arr,len,i);
}
// 排序
for (int i = len - 1; i > 0; i--)
{
swap(arr[i],arr[0]);
max_heapify(arr,i,0);
}
}
void PrintfArr(int arr[], int len)
{
for (int i = 0; i < len; i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {12,23,45,65,21,12,3,1,23,4};
int len = sizeof(arr) / sizeof(int);
PrintfArr(arr,len);
HeapSort(arr,len);
PrintfArr(arr, len);
return 0;
}