PHP 堆排序算法
最后修改于 2025 年 4 月 16 日
基本定义
算法是一种逐步解决问题或执行计算的程序。排序算法将元素按特定顺序排列。
常见的排序算法包括冒泡排序、选择排序、插入排序、归并排序、快速排序和堆排序。 它们各有不同的时间复杂度。
堆排序概述
堆排序是一种基于比较的排序算法,它使用二叉堆数据结构。 它的时间复杂度为 O(n log n),适用于所有情况。
该算法首先从输入数据构建一个最大堆。 然后它重复提取最大元素并重建堆。
堆排序实现
这是一个 PHP 中用于数值数据的基本堆排序实现
heap_sort.php
<?php function heapSort(array &$arr): void { $n = count($arr); // Build max heap for ($i = (int)($n / 2) - 1; $i >= 0; $i--) { heapify($arr, $n, $i); } // Extract elements one by one for ($i = $n - 1; $i > 0; $i--) { // Move current root to end [$arr[0], $arr[$i]] = [$arr[$i], $arr[0]]; // Heapify reduced heap heapify($arr, $i, 0); } } function heapify(array &$arr, int $n, int $i): void { $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) { [$arr[$i], $arr[$largest]] = [$arr[$largest], $arr[$i]]; heapify($arr, $n, $largest); } } $numbers = [12, 11, 13, 5, 6, 7]; heapSort($numbers); print_r($numbers);
此实现首先从输入数组构建一个最大堆。 然后它重复提取最大元素并维护堆属性。
对文本数据进行排序
堆排序也可以按字母顺序对字符串进行排序。 这是一个例子
heap_sort_strings.php
<?php function heapSortStrings(array &$arr): void { $n = count($arr); for ($i = (int)($n / 2) - 1; $i >= 0; $i--) { heapifyStrings($arr, $n, $i); } for ($i = $n - 1; $i > 0; $i--) { [$arr[0], $arr[$i]] = [$arr[$i], $arr[0]]; heapifyStrings($arr, $i, 0); } } function heapifyStrings(array &$arr, int $n, int $i): void { $largest = $i; $left = 2 * $i + 1; $right = 2 * $i + 2; if ($left < $n && strcmp($arr[$left], $arr[$largest]) > 0) { $largest = $left; } if ($right < $n && strcmp($arr[$right], $arr[$largest]) > 0) { $largest = $right; } if ($largest != $i) { [$arr[$i], $arr[$largest]] = [$arr[$largest], $arr[$i]]; heapifyStrings($arr, $n, $largest); } } $words = ["banana", "apple", "cherry", "date"]; heapSortStrings($words); print_r($words);
此版本使用 strcmp
进行字符串比较。 该算法的工作方式相同,但比较的是字符串而不是数字。
降序排序
要按降序排序,我们修改堆化函数以创建最小堆而不是最大堆
heap_sort_descending.php
<?php function heapSortDescending(array &$arr): void { $n = count($arr); for ($i = (int)($n / 2) - 1; $i >= 0; $i--) { heapifyDescending($arr, $n, $i); } for ($i = $n - 1; $i > 0; $i--) { [$arr[0], $arr[$i]] = [$arr[$i], $arr[0]]; heapifyDescending($arr, $i, 0); } } function heapifyDescending(array &$arr, int $n, int $i): void { $smallest = $i; $left = 2 * $i + 1; $right = 2 * $i + 2; if ($left < $n && $arr[$left] < $arr[$smallest]) { $smallest = $left; } if ($right < $n && $arr[$right] < $arr[$smallest]) { $smallest = $right; } if ($smallest != $i) { [$arr[$i], $arr[$smallest]] = [$arr[$smallest], $arr[$i]]; heapifyDescending($arr, $n, $smallest); } } $numbers = [12, 11, 13, 5, 6, 7]; heapSortDescending($numbers); print_r($numbers);
此实现找到最小的元素而不是最大的元素,从而得到降序。 同样的方法也适用于字符串,通过修改比较。
堆排序与快速排序
堆排序和快速排序都是高效的排序算法,平均时间复杂度为 O(n log n)。 但是,它们具有不同的特性。
快速排序通常在实践中更快,因为它具有更好的缓存性能和更小的常数因子。 然而,堆排序在最坏情况下保证了 O(n log n) 的性能。
基准测试比较
让我们通过基准测试比较堆排序和快速排序的性能
sort_benchmark.php
<?php function quickSort(array &$arr, int $low, int $high): void { if ($low < $high) { $pi = partition($arr, $low, $high); quickSort($arr, $low, $pi - 1); quickSort($arr, $pi + 1, $high); } } function partition(array &$arr, int $low, int $high): int { $pivot = $arr[$high]; $i = $low - 1; for ($j = $low; $j <= $high - 1; $j++) { if ($arr[$j] < $pivot) { $i++; [$arr[$i], $arr[$j]] = [$arr[$j], $arr[$i]]; } } [$arr[$i + 1], $arr[$high]] = [$arr[$high], $arr[$i + 1]]; return $i + 1; } // Generate large random array $largeArray = []; for ($i = 0; $i < 10000; $i++) { $largeArray[] = rand(1, 100000); } // Benchmark heap sort $heapArray = $largeArray; $heapStart = microtime(true); heapSort($heapArray); $heapTime = microtime(true) - $heapStart; // Benchmark quick sort $quickArray = $largeArray; $quickStart = microtime(true); quickSort($quickArray, 0, count($quickArray) - 1); $quickTime = microtime(true) - $quickStart; echo "Heap sort time: " . number_format($heapTime, 6) . " seconds\n"; echo "Quick sort time: " . number_format($quickTime, 6) . " seconds\n";
此基准测试创建一个大的随机数组,并测量两种算法的排序时间。 快速排序通常在随机数据上表现更好。
何时使用堆排序
- 最坏情况保证: 当您需要保证 O(n log n) 的性能时。
- 内存限制: 堆排序是原地排序 (O(1) 空间)。
- 外部排序: 用于排序不适合内存的数据。
- 优先级队列: 堆结构在排序之外也很有用。
来源
本教程涵盖了 PHP 堆排序算法,并提供了数值和文本数据的示例,包括升序和降序排序。
作者
列出 所有 PHP 教程。