JavaScript 学习-希尔排序方法

520 阅读3分钟

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

上一篇文章学习了排序方法, 另更多更文学习了 JavaScript 中的

本文来继续学习 JavaScript 中的排序方法: 在实际工作中经常用到排序算法

JavaScript 排序方法-希尔排序

希尔排序, 也称缩小增量排序算法, 是插入排序的一种更高效的改进版本。但希尔排序也是非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  • 插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率;
  • 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位;

希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序, 待整个序列中的记录“基本有序”时, 再对全体记录进行依次直接插入排序。

1. 算法步骤

选择一个增量序列 t1, t2, ……, tk, 其中 ti > tj, tk = 1;按增量序列个数 k, 对序列进行 k 趟排序;每趟排序, 根据对应的增量 ti, 将待排序列分割成若干长度为 m 的子序列, 分别对各子表进行直接插入排序。仅增量因子为 1 时, 整个序列作为一个表来处理, 表长度即为整个序列的长度。

2. JavaScript 代码实现

// 给公司的 20000+ 条数据排个序, // 但是由于排序的操作会频繁发生, // 如果操作执行的时间很慢,则会严重降低用户体验,

/**
 * 1. 希尔排序 (todo 待验证)
 * 核心: 通过动态定义的 gap 来排序, 先排序距离较远的元素, 再逐渐递进
 * @param {Array} arr
 * 耗时: 15ms
 */
function shellSort(arr) {
  var len = arr.length,
    temp,
    gap = 1
  while (gap < len / 3) {
    gap = gap * 3 + 1
  }
  for (gap; gap > 0; gap = Math.floor(gap / 3)) {
    for (var i = gap; i < len; i++) {
      temp = arr[i]
      for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
        arr[j + gap] = arr[j]
      }
      arr[j + gap] = temp
    }
  }
  return arr
}
// 引入下面的 测试代码耗时的方法: 进行测试希尔排序对处理20000+条数据的排序耗时:
getFnRunTime(shellSort)

测试代码运行耗时的函数

// 生成一个有20万条数据长度的数组:
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
  )
}

更多阅读