希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:

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

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

1. 算法步骤

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

2. 动图演示

Sorting_shellsort_anim.gif

3.代码

  1. function shellSort(arr) {
  2. let len = arr.length,
  3. temp,
  4. gap = 1
  5. console.time('希尔排序耗时')
  6. while (gap < len / 3) {
  7. //动态定义间隔序列
  8. gap = gap * 3 + 1
  9. }
  10. for (gap; gap > 0; gap = Math.floor(gap / 3)) {
  11. for (let i = gap; i < len; i++) {
  12. temp = arr[i]
  13. let j = i - gap
  14. for (; j >= 0 && arr[j] > temp; j -= gap) {
  15. arr[j + gap] = arr[j]
  16. }
  17. arr[j + gap] = temp
  18. console.log('arr :', arr)
  19. }
  20. }
  21. console.timeEnd('希尔排序耗时')
  22. return arr
  23. }
  1. if (!Array.isArray(nums)) {
  2. throw new Error('请输入一个数组')
  3. }
  4. let len = nums.length
  5. if (len < 2) {
  6. return nums
  7. }
  8. let gap = 1
  9. let i, j
  10. let temp
  11. while (gap < len / 3) {
  12. gap = gap * 3 + 1
  13. }
  14. for (gap; gap > 0; gap = Math.floor(gap / 3)) {
  15. for (i = gap; i < len; i++) {
  16. j = i - gap
  17. temp = nums[i]
  18. while (j >= 0 && nums[j] > temp) {
  19. nums[j + gap] = nums[j]
  20. j -= gap
  21. }
  22. nums[j + gap] = temp
  23. }
  24. }
  25. return nums