# 解题思路 or 实现原理

堆排序(Heap sort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构, 并同时满足堆积的性质: 即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

  • 大顶堆: 每个节点的值都大于或等于其子节点的值, 在堆排序算法中用于升序排列;

  • 小顶堆: 每个节点的值都小于或等于其子节点的值, 在堆排序算法中用于降序排列;

堆排序的平均时间复杂度为 Ο(nlogn)

# 算法步骤

  • 创建一个堆 H[0……n-1];

  • 把堆首(最大值)和堆尾互换;

  • 把堆的尺寸缩小 1, 并调用 shift_down(0), 目的是把新的数组顶端数据调整到相应位置;

  • 重复步骤 2, 直到堆的尺寸为 1。

heapSort

# 实现代码

/*
 * @Author: Rainy
 * @Date: 2019-11-14 19:25:01
 * @LastEditors: Rainy
 * @LastEditTime: 2019-11-24 20:50:03
 */

import { NumberArrayMap } from 'types';

export function heapSort(arr: NumberArrayMap): NumberArrayMap {
  let len = arr.length;
  if (len < 2) {
    return arr;
  }
  buildMaxHeap(arr, len);

  for (let i = arr.length - 1; i > 0; i--) {
    swap(arr, 0, i);
    len--;
    heapify(arr, 0, len);
  }
  return arr;
}

function buildMaxHeap(arr: NumberArrayMap, len: number) {
  for (let i = Math.floor(len / 2); i >= 0; i--) {
    heapify(arr, i, len);
  }
}

function heapify(arr: NumberArrayMap, i: number, len: number) {
  let left = 2 * i + 1;
  let right = 2 * i + 2;
  let largest = i;

  if (left < len && arr[left] > arr[largest]) {
    largest = left;
  }

  if (right < len && arr[right] > arr[largest]) {
    largest = right;
  }

  if (largest !== i) {
    swap(arr, i, largest);
    heapify(arr, largest, len);
  }
}

function swap(arr: NumberArrayMap, i: number, j: number) {
  [arr[i], arr[j]] = [arr[j], arr[i]];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

# 参考

heapSort (opens new window)