Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

堆排序 #44

Open
Geekhyt opened this issue Feb 26, 2021 · 0 comments
Open

堆排序 #44

Geekhyt opened this issue Feb 26, 2021 · 0 comments

Comments

@Geekhyt
Copy link
Owner

Geekhyt commented Feb 26, 2021

堆排序相比其他几种排序代码会有些复杂,不过没关系,我们先来看一些前置知识,可以帮助我们更好的理解堆排序。

堆排序顾名思义就是要利用堆这种数据结构进行排序。堆是一种特殊的树,满足以下两点就是堆:

  1. 堆是一个完全二叉树
  2. 堆中每一个节点的值都必须大于等于(或小于等于)其子树中的每个节点的值

每个节点的值都大于等于子树中每个节点值的堆,叫做大顶堆,每个节点的值都小于等于子树中每个节点值的堆,叫做小顶堆

也就是说,大顶堆中,根节点是堆中最大的元素。小顶堆中,根节点是堆中最小的元素

如果你对树这种数据结构还不是很了解,可以移步我的这篇专栏“树”业有专攻

堆如果用一个数组表示的话,给定一个节点的下标 i (i从1开始),那么它的父节点一定为 A[i / 2],左子节点为 A[2i],右子节点为 A[2i + 1]。

堆排序包含两个过程,建堆和排序。首先构建一个大顶堆,也就是将最大值存储在根节点(i = 1),每次取大顶堆的根节点与堆的最后一个节点进行交换,此时最大值放入了有效序列的最后一位,并且有效序列减 1,有效堆依然保持完全二叉树的结构,然后进行堆化成为新的大顶堆。重复此操作,直到有效堆的长度为 0,排序完成。

const heapSort = function(arr) {
    buildHeap(arr, arr.length - 1)
    let heapSize = arr.length - 1 // 初始化堆的有效序列长度
    for (let i = arr.length - 1; i > 1; i--) {
        swap(arr, 1, i) // 交换堆顶元素与最后一个有效子元素
        heapSize-- // 有效序列长度减 1
        heapify(arr, heapSize, 1) // 堆化有效序列
    }
    return arr
}

// 构建大顶堆
const buildHeap = function(items, heapSize) {
    // 从后往前并不是从序列的最后一个元素开始,而是从最后一个非叶子节点开始,这是因为,叶子节点没有子节点,不需要自上而下式堆化。
    // 最后一个子节点的父节点为 n/2 ,所以从 n/2 位置节点开始堆化
    for (let i = Math.floor(heapSize / 2); i >= 1; i--) {
        heapify(items, heapSize, i)
    }
}
// 堆化
const heapify = function(arr, heapSize, i) {
    while (true) {
        let maxIndex = i
        if (2 * i <= heapSize && arr[i] < arr[i * 2]) {
            maxIndex = i * 2
        }
        if (2 * i + 1 <= heapSize && arr[maxIndex] < arr[i * 2 + 1]) {
            maxIndex = i * 2 + 1
        }
        if (maxIndex === i) break
        swap(arr, i, maxIndex)
        i = maxIndex
    }
}

// 交换工具函数
const swap = function(arr, i, j) {
    let temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp
}
  • 时间复杂度: O(nlogn)
  • 空间复杂度: O(1)
  • 不稳定
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant