算法总结JS版(四)—— 希尔排序(Shell Sort)

来源:互联网 发布:淘宝pr剪切教程 编辑:程序博客网 时间:2024/05/29 09:16

(1)算法简介

希尔排序的核心在于间隔序列的设定。1959年Shell发明; 第一个突破O(n^2)的排序算法;是简单插入排序的改进版;它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
!划重点:在这里重点解释下为什么Shell Sort时间复杂度为O(n*logn),比插入排序高级:该方法的基本思想是:先将整个待排元素序列分割为若干个子序列(由相隔某个‘增量’的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,带这个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
!注意因为直接插入排序在元素基本有序的情况下(接近最好情况)效率是很高的,而在开始最后一次处理时(即增量为1时),大部分元素都将在正确的位置,算法就不必对很多元素进行交换,这是比插入元素高级的地方。因此希尔排序在时间效率上有较大的提高。
另外个人感觉增量的选择不会太影响效率(可能会稍微有一点,但不大),自己测试了几次,看不出什么,因为影响因素很多,然后看了很多博客,有的说素数比较好;有的说没影响;有的是使用动态的定义间隔序列。动态定义间隔序列的算法是《算法(第4版》的合著者Robert Sedgewick提出的。
以上纯属个人观点,如有哪位大佬有正确的观点,请在评论赐教。

(2)算法描述

见(1)中划重点

(3)Javascript代码实现

function shellSort(arr) {    var len = arr.length,        temp,        //增量(一般第一趟取长度的一半向下取整)        gap = Math.floor(len / 2);     //每一趟过后增量会变成原来的一半并向下取整,可知最后一趟增量肯定是1    //增量为1即实现普通的插入排序,执行完毕整个排序肯定就完成了    //而最后一趟增量为1过完时,增量变成0    //gap > 0是为了控制当增量变成0时,整个排序已完成,停止排序    for (gap; gap > 0; gap = Math.floor(gap / 2)) {        //以下开始即普通的插入排序(按分好的组进行插入)        //初始i=gap是为了让第gap+1个数和第一个数相比        //i<len是从第gap+1个数开始之后的每一个数都和之前差n个增量的数相比        for (var i = gap; i < len; i++) {            //保存当前要拿来对比插入的数(比较数)            temp = arr[i];            //j=i-gap是将temp和之前差一个增量的数相比,arr[j]即被比较数            //j>=0是按增量向前比,一直比到向前减一个增量没有数 即下标j<0            //arr[j] > temp是判断被比较数是否大于比较数,            //如果大于,将被比较数向后移一个增量的位置,            //即比较数的位置 i或者j+gap            //j -= gap 每次在上次被比较数的基础上向前比差一个增量的数            for (var j = i-gap; j>=0 && arr[j]>temp; j-=gap) {                //将被比较数向后移一个增量的位置,                //即比较数的位置 i或者j+gap                arr[j + gap] = arr[j];            }            arr[j + gap] = temp;//插入比较数        }    }    return arr;}var arr = [99, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];console.log(shellSort(arr));//输出[2, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50, 99]

(4)算法分析
最佳情况:输入数组按升序排列。T(n) = O(nlog2 n)
最坏情况:输入数组按降序排列。T(n) = O(nlog2 n)
平均情况:T(n) =O(nlog n)

原创粉丝点击