数组排序简介-堆排序(Heap sort)

 基本思想

        借用「堆结构」所设计的排序算法。将数组转化为大顶堆,重复从大顶堆中取出数值最大的节点,并让剩余的堆结构继续维持大顶堆性质。

算法步骤

  1. 构建初始大顶堆

    1. 定义一个数组实现的堆结构,将原始数组的元素依次存入堆结构的数组中(初始顺序不变)。
    2. 从数组的中间位置开始,从右至左,依次通过「下移调整」将数组转换为一个大顶堆。
  2. 交换元素,调整堆

    1. 交换堆顶元素(第 1 个元素)与末尾(最后 1 个元素)的位置,交换完成后,堆的长度减 1。
    2. 交换元素之后,由于堆顶元素发生了改变,需要从根节点开始,对当前堆进行「下移调整」,使其保持堆的特性。
  3. 重复交换和调整堆

    1. 重复第 2 步,直到堆的大小为 1 时,此时大顶堆的数组已经完全有序。

适用场景

        堆排序是一种比较高效的排序算法,具有以下适用场景:

        大规模数据排序内存受限环境动态数据排序求第 K 大(小)元素

排序稳定性

        在进行「下移调整」时,相等元素的相对位置可能会发生变化。因此,堆排序是一种 不稳定排序算法

代码实现(golang)

func heapSort(arr []int) []int {
    n := len(arr)

    // 构建最大堆
    for i := n/2 - 1; i >= 0; i-- {
        heapify(arr, n, i)
    }

    // 一个个取出堆顶元素并调整堆
    for i := n - 1; i >= 0; i-- {
        arr[0], arr[i] = arr[i], arr[0]
        heapify(arr, i, 0)
    }

    return arr
}

func heapify(arr []int, n, i int) {
    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)
    }
}


func main() {
    arr := []int{12, 11, 13, 5, 6, 7}
    sortedArr := heapSort(arr)
    fmt.Println(sortedArr)
}

猜你喜欢

转载自blog.csdn.net/Runing_WoNiu/article/details/143354392