什么是堆排序
堆排序是我们经常使用的排序算法,它是利用堆的结构进行排序,堆是一种二叉树结构,并且它的父节点的值都大于子节点或者都小于子节点,如果大于,就是大顶堆,如果小于就是小顶堆。
根据堆的定义,我们只要不断构造大顶堆,然后取出堆顶元素就可以完成堆排序。
代码实现
// 堆排序
function heapSort(&$arr)
{
// 初始化大顶堆
initHeap($arr);
// 开始交换首尾节点,并每次减少一个末尾节点再调整堆,直到剩下一个元素
for ($end = count($arr) - 1; $end >= 0; $end--) {
$temp = $arr[0];
$arr[0] = $arr[$end];
$arr[$end] = $temp;
ajustNodes($arr, 0, $end - 1);
}
}
// 初始化最大堆,从最后一个非叶子节点开始,最后一个非叶子节点编号为 数组长度/2 向下取整
function initHeap(&$arr)
{
$len = count($arr);
for ($start = floor($len / 2) - 1; $start > 0; $start--) {
ajustNodes($arr, $start, $len - 1);
}
}
// 调整节点
// @param $arr 待调整数组
// @param $start 调整的父节点坐标
// @param $end 待调整数组结束节点坐标
function ajustNodes(&$arr, $start, $end)
{
$maxInx = $start;
$len = $end + 1; // 待调整部分长度
$leftChildInx = ($start + 1) * 2 - 1; // 左孩子坐标
$rightChildInx = ($start + 1) * 2; // 右孩子坐标
// 如果待调整部分有左孩子
if ($leftChildInx + 1 < = $len) {
// 获取最小节点坐标
if ($arr[$maxInx] < $arr[$leftChildInx]) {
$maxInx = $leftChildInx;
}
// 如果待调整部分有右子节点
if ($rightChildInx + 1 <= $len) {
if ($arr[$maxInx] < $arr[$rightChildInx]) {
$maxInx = $rightChildInx;
}
}
}
// 交换父节点和最大节点
if ($start != $maxInx) {
$temp = $arr[$start];
$arr[$start] = $arr[$maxInx];
$arr[$maxInx] = $temp;
// 如果交换后的子节点还有子节点,继续调整
if (($maxInx + 1) * 2 <= $len) {
ajustNodes($arr, $maxInx, $end);
}
}
}
$arr = array(1, 5, 3, 7, 9, 10, 2, 8);
heapSort($arr);
print_r($arr);