背景
由于 插入排序, 只会交换相邻元素, 因此只能一点点的从数组的一端移动到另一端, 如意 最小的元素 正好在 数组的末端, 那么 就得移动 次 , 因此 希尔排序在插入排序的基础上进行了改进, 交换不相邻的元素进行对数组进行局部排序, 并最终进行数组排序
希尔排序
希尔排序: 将全部元素分为几个部分来进行排序, 这样可以使的一个元素可以一次性的移动一大步, 然后不断的通过减小步长进行排序, 到最后进行 普通的插入排序, 此时 基本上 整个元素 近乎已经 排好序, 这样插入排序 就会更快一点
数据结构: 数组
时间复杂度
根据步长的序列不同而不同;
最好的时间复杂度:
最坏的时间复杂度:
示例
现有一个无序数组 const arr = [823,427,26,822,81,931,585,424]
- 第一步: 设置步长h为 数组的一半,
h = arr.length / 2 = 4得到一个类似下面的样子
-
第二步: 对列进行排序得到, 得到一个
[81, 427, 26, 424, 823, 931, 585, 822] -
第三步: 将步长h, 继续缩小 一半;
h = h / 2 = 2, 可以得到看似以下结构 -
第四步: 对列进行排序得到
[26, 424, 81, 427, 585, 822, 823, 931] -
第五步: 将步长继续缩小一半, 此时 为 1, 那么就开始了插入排序,
[26, 81, 424, 427, 585, 822, 823, 931]
代码实现(Typescript)
/**
* 生成指定的随机数
* @param count {number}
* @param min {number}
* @param max {number}
* @returns Array<number>
*/
function getRandomInteger(count: number = 1, min: number = 0, max: number = 1000): Array<number> {
const res: Array<number> = []
for (let i = 0; i < count; i ++ ){
const random = Math.floor(Math.random() * (max - min) + min)
res.push(random)
}
return res
}
/**
* 希尔排序
* @param arr
* @returns
*/
function shellSort (arr: Array<number>): Array<number> {
if (arr.length < 2) return arr
for (let step = arr.length >> 1; step > 0; step >>= 1) {
for (let i = step; i < arr.length; i++) {
const curValue:number = arr[i]
let j: number = i - step
for (; j >= 0 && arr[j] > curValue; j -= step) {
arr[j + step] = arr[j]
}
arr[j + step] = curValue
}
}
return arr
}
const randoms: Array<number> = getRandomInteger(10)
console.log("排序前:" + randoms) // 排序前:934,173,734,595,779,278,554,440,562,206
console.log("排序后:" + shellSort(randoms)) // 排序后:173,206,278,440,554,562,595,734,779,934