堆排序

堆排序（Heapsort）是指利用-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-这种数据结构所设计的一种排序算法。-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-是一个近似完全二叉树的结构，并同时满足堆积的性质：即子节点的键值或索引总是小于（或者大于）它的父节点。
概述.
若以升序排序说明，把阵列转换成最大堆积（Max-Heap Heap），这是一种满足最大堆积性质（Max-Heap Property）的二元树：对于除了根之外的每个节点i, A≥ A[i。
重复从最大堆积取出数值最大的结点（把根结点和最后一个结点交换，把交换后的最后一个结点移出堆），并让残余的堆积维持最大堆积性质。
-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-节点的访问.
通常-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-是通过一维数组来实现的。在阵列起始位置为0的情形中：
-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-的操作.
在-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-的资料结构中，-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-中的最大值总是位于根节点（在优先队列中使用-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-的话-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-中的最小值位于根节点）。-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-中定义以下几种操作：
实作范例.
C++.
<syntaxhighlight lang="cpp">
using namespace std;
void max_heapify(int arr[], int start, int end) {
void heap_sort(int arr[], int len) {
int main() {
</syntaxhighlight>
Java.
<syntaxhighlight lang=java>
import java.util.Arrays;
public class HeapSort {
</syntaxhighlight>
Python.
<syntaxhighlight lang=python>
def heap_sort(lst):
if __name__ == "__main__":
</syntaxhighlight>
JavaScript.
<syntaxhighlight lang=javascript>
Array.prototype.heap_sort = function() {
 var arr = this.slice(0);
 function swap(i, j) {
 var tmp = arr;
 arr= arr[j;
 arr = tmp;
 function max_heapify(start, end) {
 //建立父节点指标和子节点指标
 var dad = start;
 var son = dad * 2 + 1;
 if (son >= end)//若子节点指标超过范围直接跳出函数
 return;
 if (son + 1 < end && arr< arr[son + 1)//先比较两个子节点大小，选择最大的
 son++;
 if (arr< arr[son) {//如果父节点小于子节点时，交换父子内容再继续子节点和孙节点比较
 swap(dad, son);
 max_heapify(son, end);
 var len = arr.length;
 //初始化，i从最后一个父节点开始调整
 for (var i = Math.floor(len / 2) - 1; i >= 0; i--)
 max_heapify(i, len);
 //先将第一个元素和已排好元素前一位做交换，再从新调整，直到排序完毕
 for (var i = len - 1; i > 0; i--) {
 swap(0, i);
 max_heapify(0, i);
 return arr;
var a = 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6;
console.log(a.heap_sort());
</syntaxhighlight>
PHP.
<syntaxhighlight lang=php>
<?php
function swap(&$x, &$y) {
 $t = $x;
 $x = $y;
 $y = $t;
function max_heapify(&$arr, $start, $end) {
 //建立父节点指标和子节点指标
 $dad = $start;
 $son = $dad * 2 + 1;
 if ($son >= $end)//若子节点指标超过范围直接跳出函数
 return;
 if ($son + 1 < $end && $arr[$son] < $arr[$son + 1])//先比较两个子节点大小，选择最大的
 $son++;
 if ($arr[$dad] <= $arr[$son]) {//如果父节点小于子节点时，交换父子内容再继续子节点和孙节点比较
 swap($arr[$dad], $arr[$son]);
 max_heapify($arr, $son, $end);
function heap_sort($arr) {
 $len = count($arr);
 //初始化，i从最后一个父节点开始调整
 for ($i = ceil($len/2) - 1; $i >= 0; $i--)
 max_heapify($arr, $i, $len);
 //先将第一个元素和已排好元素前一位做交换，再从新调整，直到排序完毕
 for ($i = $len - 1; $i > 0; $i--) {
 swap($arr$arr[$i);
 max_heapify($arr, 0, $i);
 return $arr;
$arr = array(3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6);
$arr = heap_sort($arr);
for ($i = 0; $i < count($arr); $i++)
 echo $arr[$i] . ' ';
</syntaxhighlight>
Go.
<syntaxhighlight lang=go>
package main
import (
 "fmt"
func HeapSort(array []int) {
 m := len(array)
 s := m/2
 for i := s; i > -1; i-- {
 heap(array, i, m-1)
 for i := m-1; i > 0; i-- {
 arrayarray[0 = arrayarray[i
 heap(array, 0, i-1)
func heap(array []int, i, end int){
 l := 2*i+1
 if l > end {
 return
 n := l
 r := 2*i+2
 if r <= end && array>array{
 n = r
 if array> array[n{
 return
 arrayarray[i = arrayarray[n
 heap(array, n, end)
func main() {
 array := []int{
 55, 94,87,1,4,32,11,77,39,42,64,53,70,12,9,
 HeapSort(array)
 fmt.Println(array)
</syntaxhighlight>
Julia (程式语言).
<syntaxhighlight lang="julia">
function HeapSort(array)
end
</syntaxhighlight>
Rust.
<syntaxhighlight lang="rust">
fn max_heapify<T: Ord + Copy>(data: &mut , pos: usize, end: usize) {
fn heap_sort<T:Ord+Copy>(data: &mut) {
fn main() {
</syntaxhighlight>
原地堆排序.
基于以上-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-相关的操作，我们可以很容易的定义堆排序。例如，假设我们已经读入一系列数据并创建了一个-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-，一个最直观的算法就是反复的调用codice_1函数，因为该函数总是能够返回-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-中最大的值，然后把它从-{zh-cn:堆;zh-tw:堆积;zh-hk:堆积;}-中删除，从而对这一系列返回值的输出就得到了该序列的降序排列。真正的原地堆排序使用了另外一个小技巧。堆排序的过程是：
平均复杂度.
堆排序的平均时间复杂度为formula_6，空间复杂度为formula_7。