活动地址:CSDN21天学习挑战赛
希尔排序的历史
希尔排序是对插入排序的一种高效的改进版,并且效率比插入排序更快。
希尔排序按其设计者希尔的名字命名,该算法由1959年公布。
在简单排序出现后的很长一段时间内,人们发明了各种各样的算法,但是最终发现排序算法的时间复杂度都是O(n^2),似乎没法超越了。此时,计算机学术界充斥着排序算法不可能突破O(n²)的声音。终于,有一天,一位科学家发布超越O(n²)了新的排序算法,为了纪念这个里程碑。用shell命名了该算法。
插入排序的问题
插入排序执行到一半的时候,标记符左边这部分数据项都是排好序的,而标记符右边的数据项是没有排序的,这个时候取出指向的那个数据项,把它存储在一个临时变量中,接着,从刚刚衣橱的位置左边第一个单元开始,每次把有序的数据项向右移动一个单元,直到存储在临时变量中的数据项可以插入成功。
插入排序的问题:
假设一个很小的数据项在很靠右的位置上,这里本来应该是较大的数据项的位置,把这个小数据项移动到正确的位置,所有的数据项都必修向右移动一位,如果每个步骤对数据项都进行N次复制,平均下来是移动N/2,N个元素就是N*N/2 = N^2/2,所以我们通常认为插入排序的算法是O(n²).如果有某种方式不需要一个个移动所有中间的数据项,那么算法效率就有很大的提高。希尔排序就是这这种方式。
希尔排序思想
希尔排序,在插入排序的基础上做了很大改善,它会先比较距离较远的元素,使用这种方案可以使离正确位置很远的元素更快地回到合适的位置。
希尔排序的思想是分组排序,通过定义一个间隔序列来表示在排序过程中比较的元素之间的有多远的间隔,把具有相同间隔的元素作为一组,进行排序。
在希尔排序过程中,元素的间隔会不断缩小,直到间隔为1,即相邻元素。
希尔排序过程
首先对间隔为5 的元素进行检查调换,然后对间隔为3的元素进行检查调换,最后对相邻的元素进行调换。
希尔排序代码
function shellSort(arr){
let gaps = [5,3,1];
for(let g = 0;g < gaps.length;g++){
for(let i = gaps[g]; i<arr.length; i++){
let temp = arr[i];
for(let j = i; j >= gaps[g] && arr[j - gaps[g]] > temp; j -= gaps[g]){
arr[j] = arr[j - gaps[g]]);
}
arr[j] = temp;
}
}
return arr;
}
希尔排序的效率是与增量有关的,但是它的效率证明非常困难,甚至某些增量的效率到目前为止都没有被证明出来。但是经过统计,希尔排序使用原始增量,最坏的情况下时间复杂度为O(n²),通常情况下好于O(n²)。