希尔排序

原理解析

先将整个待排数组分割成若干个子数组(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个数组中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下效率是很高的,因此希尔排序在时间效率上较大提高。

范例演示

3 1 7 2 5 0 4 6

gap: 4 3 1 7 2 5 0 4 6
3 0 4 2 5 1 7 6
gap: 2 3 0 4 2 5 1 7 6
3 0 4 1 5 2 7 6
gap: 1 3 0 4 1 5 2 7 6
0 1 2 3 4 5 6 7

实现方式


function shellSort(arr) {
  var temp
  var len = arr.length
  for (var gap = len >> 1; gap > 0; gap = gap >>=1) {
    for (var i = gap; i < len; i++) {
      temp = arr[i]
      for( j = i - gap; j >=0 && arr[j] > temp; j -= gap) {
        arr[j + gap] = arr[j]
      }
      arr[j + gap] = temp
    }
    console.log(arr)
  }
}

var arr = [3, 1, 7, 2, 5, 0, 4, 6]
shellSort(arr)
console.log(arr)

效率测试

下面我们测试排序性能。以下的代码中,randomArr 函数会生成一个随机数组, 数组长度默认是100, 最大值默认值是1000。 console.time 和 console.end 用来记录排序时间。


var arr = randomArr(10000, 100)
console.time('shellSort')
shellSort(arr)
console.timeEnd('shellSort')


function randomArr( arrLen = 100, maxValue = 1000 ) {
  let arr = []
  for(let i = 0; i < arrLen; i++) {
    arr[i] = Math.floor((maxValue+1)*Math.random())
  }
  return arr
}

function shellSort(arr) {
  var temp
  var len = arr.length
  for (var gap = len >> 1; gap > 0; gap = gap >>=1) {
    for (var i = gap; i < len; i++) {
      temp = arr[i]
      for( j = i - gap; j >=0 && arr[j] > temp; j -= gap) {
        arr[j + gap] = arr[j]
      }
      arr[j + gap] = temp
    }
  }
}

经浏览器测试,对于长度为10000的数组,排序约需要2ms(100次平均值), 对于长度为100000的数组,排序约需要 23.76ms(100次平均值)。

复杂度分析

时间复杂度为 O(nlog2n)

results matching ""

    No results matching ""