学习经典排序算法-堆排序(Heapsort)

572 阅读3分钟

这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

上一篇文章学习了排序方法, 另更多更文学习 JavaScript 的系列小总结更多阅读 & 经典排序算法

本文来继续学习经典排序方法: 堆排序 Heapsort

JS实现排序算法-堆排序 Heapsort

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

堆排序分为两种方法:

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

堆排序 算法步骤

  1. 将待排序序列构建成一个堆 H[0……n-1],根据(升序降序需求)选择大顶堆或小顶堆;
  2. 把堆首(最大值)和堆尾互换;
  3. 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
  4. 重复步骤 2,直到堆的尺寸为 1。

堆排序 JS 代码实现:

  1. 功能函数封装
var len // 因为声明的多个函数都需要数据长度,所以把len设置成为全局变量

function buildMaxHeap(arr) {
  // 建立大顶堆
  len = arr.length
  for (var i = Math.floor(len / 2); i >= 0; i--) {
    heapify(arr, i)
  }
}

function heapify(arr, i) {
  // 堆调整
  var left = 2 * i + 1,
    right = 2 * i + 2,
    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)
  }
}

function swap(arr, i, j) {
  var temp = arr[i]
  arr[i] = arr[j]
  arr[j] = temp
}
  1. 排序算法 heapSort() 函数实现
function heapSort(arr) {
  buildMaxHeap(arr)

  for (var i = arr.length - 1; i > 0; i--) {
    swap(arr, 0, i)
    len--
    heapify(arr, 0)
  }
  return arr
}
// 引入下面的 测试代码耗时的方法: 进行测试希尔排序对处理20000+条数据的排序耗时:
getFnRunTime(heapSort)

代码运行耗时方法

const testArrFn = function () {
  let arr = []
  const count = 200000
  for (let i = 0; i < count; i++) {
    arr[i] = Math.floor(Math.random() * 50 + 1)
  }
  return arr
}
let testArr = testArrFn()

let len = testArr.length
/**
 * @desc 测试函数执行的时间
 */
module.exports = async function getFnRunTime(fn) {
  let startTime = Date.now(),
    endTime
  let result = await fn(testArr)
  endTime = Date.now()
  console.log(testArr, result)
  console.log(`total time: ${endTime - startTime}ms, `, "test array'length: " + len, result.length)
}

更多阅读

经典排序算法: