JavaScript希尔排序

JavaScript希尔排序

1 思路

希尔排序是一种基于插入排序的快速排序算法,也成为缩小增量排序。简单插入排序对于大规模乱序数组很慢,因为元素只能一点一点地从数组的一端移动到另一端。希尔排序为了加快速度简单地改进了插入排序,同时该算法是冲破O(n2)的第一批算法之一。

希尔排序是把数组按照一定的增量分组,对每组使用直接插入排序算法排序;然后缩小增量继续分组排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个数组被分成一组,再次排序,就可以完成整个数组的排序。

增量的选择:

  1. 希尔建议的间距是N/2,每一趟排序分成两半,也就是说,对于N=100的数组,增量间隔序列为50,25,12,6,3,1。
  2. Hibbard增量序列,增量的算法为2k-1,也就是1、3、5、7…等,这种算法最坏复杂度为O(N3/2),猜想的平均复杂度是O(N5/4),目前尚未被证明。
  3. Sedgewick增量序列,{1,5,19,41,109,…},该序列中的项是94i-92i+1,或者是4i-3*2i+1。这种增量最坏复杂度为O(N4/3),平均复杂度是O(N7/6),但是均未被证明。

示例:对数组 [5,2,3,1,4,3,2,1] 进行从小到大排序

增量排序结果
Math.floor(8/2)=4第一组:5和4进行排序,5比4大,两数交换位置,排序后结果为 [4,2,3,1,5,3,2,1]
第二组:2和3进行排序,2比3小,无需交换位置,排序后结果: [4,2,3,1,5,3,2,1]
第三组:3和2进行排序,3比2大,两数交换位置,排序后结果: [4,2,2,1,5,3,3,1]
第四组:1和1进行排序,两数相同,无需交换位置,排序后结果: [4,2,2,1,5,3,3,1]
4/2=2第一组:[4,2,5,3]进行排序,排序后结果:[2,3,4,5],数组整体结果: [2,2,3,1,4,3,5,1]
第二组: [2,1,3,1]进行排序,排序后结果:[1,1,2,3],数组整体结果: [2,1,3,1,4,2,5,3]
2/2=1增量为1时,按照插入排序正常过程进行排序

2 代码实现

示例代码:从小到大排序

function shellSort(arr) { // 参数为需要排序的数组

    // 获取初始的增量
    let gap = Math.floor(arr.length / 2);

    while (gap >= 1) { // 增量小于1时结束循环

        // 从gap开始遍历,因为插入排序假设第一个是有序的
        for (let i = gap; i < arr.length; i++) {
            let j = i; // 为插入排序从后向前排序提供条件

            // 如果排序的后面的数字小于前面的,交换两个数的位置
            while (arr[j] < arr[j - gap] && j - gap >= 0) {
                let temp = arr[j];
                arr[j] = arr[j - gap];
                arr[j - gap] = temp;

                // j减小gap从后向前遍历
                j -= gap;
            }
        }

        // 增量每次都减小一半
        gap = Math.floor(gap / 2);
    }

    return arr;
}

示例代码:从大到小排序

function shellSort(arr) { // 参数为需要排序的数组
    // 获取初始的增量
    let gap = Math.floor(arr.length / 2);

    while (gap >= 1) { // 增量小于1时结束循环

        // 从gap开始遍历,因为插入排序假设第一个是有序的
        for (let i = gap; i < arr.length; i++) {
            let j = i; // 为插入排序从后向前排序提供条件

            // 如果排序的后面的数字大于前面的,交换两个数的位置
            while (arr[j] > arr[j - gap] && j - gap >= 0) {
                let temp = arr[j];
                arr[j] = arr[j - gap];
                arr[j - gap] = temp;

                // j减小gap从后向前遍历
                j -= gap;
            }
        }

        // 增量每次都减小一半
        gap = Math.floor(gap / 2);
    }

    return arr;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值