1. 堆排序原理简介
堆排序是一种基于完全二叉树的排序算法,基本原理是将待排序的序列构造成一个大顶堆或者小顶堆,然后依次将堆顶元素取出放到有序区,再重新调整堆,重复这个过程直到整个序列有序。
堆排序的优势是可以同时通过升序和降序来进行排序,且平均时间复杂度为O(nlogn)。
2. 构建堆的过程
在堆排序中,需要首先构建一个堆,可以通过不断调用heapify()函数来实现。
2.1 heapify()函数
function heapify(&$arr, $n, $i) {
$largest = $i;
$left = 2 * $i + 1;
$right = 2 * $i + 2;
if ($left < $n && $arr[$left] > $arr[$largest]) {
$largest = $left;
}
if ($right < $n && $arr[$right] > $arr[$largest]) {
$largest = $right;
}
if ($largest != $i) {
swap($arr[$i], $arr[$largest]);
heapify($arr, $n, $largest);
}
}
这个函数用于将指定位置的元素与其子节点进行比较,找出其中最大(或最小)的元素并进行交换。交换后,如果发生了交换,需要递归调用heapify()函数,保证堆的性质。
2.2 构建堆的过程
构建堆的过程是从最后一个非叶子节点开始,逐个向前调用heapify()函数,直到根节点。
这个过程可以通过下面的代码实现:
function buildHeap(&$arr, $n) {
$start = ($n / 2) - 1;
for ($i = $start; $i >= 0; $i--) {
heapify($arr, $n, $i);
}
}
这段代码首先计算出最后一个非叶子节点的位置,然后从最后一个非叶子节点开始向前循环,调用heapify()函数进行堆化。
3. 堆排序的实现
有了构建堆的过程后,我们就可以实现堆排序了。
3.1 堆排序函数
function heapSort(&$arr, $n) {
buildHeap($arr, $n);
for ($i = $n - 1; $i >= 1; $i--) {
// 将堆顶元素(最大值)与当前未排序区间的最后一个元素交换
swap($arr[0], $arr[$i]);
// 对未排序区间进行堆化,确保堆的性质
heapify($arr, $i, 0);
}
}
在堆排序函数中,首先调用buildHeap()函数构建初始的大顶堆,然后从最后一个元素向前循环,将堆顶元素与当前未排序区间的最后一个元素交换,并对未排序区间进行堆化。
3.2 移动堆顶元素
function swap(&$a, &$b) {
$temp = $a;
$a = $b;
$b = $temp;
}
这段代码用于交换两个元素的值。
4. 使用堆排序
可以通过下面的代码示例来使用堆排序:
$arr = [9, 2, 7, 3, 5, 8, 4, 1, 6];
$length = count($arr);
echo "原始数组:";
print_r($arr);
heapSort($arr, $length);
echo "排序后数组:";
print_r($arr);
运行结果:
[9, 2, 7, 3, 5, 8, 4, 1, 6]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
5. 小结
堆排序是一种高效的排序算法,通过构建堆和不断调整堆的性质来实现排序。它的时间复杂度为O(nlogn),且具有稳定性和灵活性。堆排序的实现主要分为构建堆和堆排序两个过程,其中构建堆需要调用heapify()函数来进行堆化操作,而堆排序则是通过交换堆顶元素和未排序区间的最后一个元素,然后对未排序区间进行堆化操作来实现。
对于PHP开发者来说,熟练掌握堆排序算法的原理和实现是非常有益的,可以在实际开发中应用到排序需求中。