堆排序利用堆的性质来对数组进行排序,也就是说它的所有操作都是在数组上进行的,类似于树状数组的形式;并不是通过实际上的二叉树排序。
要实现堆排序,首先需要了解堆排序的原理。
堆中某个结点的值总是不大于其父结点的值(大顶堆:头节点值最大)。
堆中某个结点的值总是不小于其父结点的值(小顶堆:头节点值最小)。
因为是排序算法,所以这里不用二叉树结构实现堆结构,使用数组模拟并将其想象成一棵树:
arr = { 0, 1, 2, 3, 4, 5, 6 };
上图的每个位置分别对应一个数组的元素下标
假设这个堆有序,且每个父节点的值大于等于其子节点(大顶堆):
假如上图是一个数组arr,想要在该数组末尾插入一个数字10,并且变更数组元素的顺序使得堆结构依然成立。
因为 堆中某个结点的值总是不大于或不小于其父结点的值,所以需要将2位置(8)和6位置(10)进行比较,当子节点的数值大于父节点,则该子节点和父节点进行交换,即8 与 10 交换。
完成上个步骤,将需要操作的光标变成位置2(10),继续与其父节点位置0(9)进行比较,若大于其父节点,则交换,否则跳出循环。到这里一个插入操作结束。
代码如下:
void Swap(int *arr, int x, int y)
{
int temp = 0;
temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
void HeapInsert(int *arr, int index)
{
while (arr[index] > arr[(index - 1) / 2])
{
//交换函数swap
Swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
假设对刚才的数组首元素进行变更,那么要如何使该数组保持堆数组
重复该过程,即可得到新数组
代码入下:
/*
arr: 目标数组
index: 目标节点
size: 数组大小监测
*/
void HeapIfy(int *arr, int index, int size)
{
int left = index * 2 + 1;
while (left < size)
{
//找较大子节点
int largest = (left + 1 < size && arr[left + 1] > arr[left]) ? left + 1 : left;
//比较子节点和父节点
if (arr[largest] > arr[index])
Swap(arr, largest, index);
else
break;
//循环结构
index = largest;
left = index * 2 + 1;
}
}
第一次交换:
第二次交换:
依次执行即可实现排序操作。
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
void Swap(int *arr, int x, int y)
{
int temp = 0;
temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
void HeapInsert(int *arr, int index)
{
while (arr[index] > arr[(index - 1) / 2])
{
//交换函数swap
Swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
/*
arr: 目标数组
index: 目标节点
size: 数组大小监测
*/
void HeapIfy(int *arr, int index, int size)
{
int left = index * 2 + 1;
while (left < size)
{
//找较大子节点
int largest = (left + 1 < size && arr[left + 1] > arr[left]) ? left + 1 : left;
//比较子节点和父节点
if (arr[largest] > arr[index])
Swap(arr, largest, index);
else
break;
//循环结构
index = largest;
left = index * 2 + 1;
}
}
void HeapSort(int* arr, int size)
{
int i = 0;
if (arr == NULL || size < 2)
return;
//进二叉树:
for (i = 1; i < size; i++)
{
HeapInsert(arr, i);
}
//排序:
while (size > 0)
{
Swap(arr, 0, --size);
HeapIfy(arr, 0, size);
}
}
int main()
{
int arr[] = { 2, 3, 1, 3, 4, 5, 2, 8, 4, 7, 0, 8, 9, 3, 1 };
int size = sizeof(arr) / sizeof(arr[0]);
HeapSort(arr, size);
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
system("pause");
return 0;
}