希尔排序

希尔排序

概述

希尔排序是插入排序的改进版,也称缩小增量排序。其核心思想是将原始数组按增量分成多个子序列,对每组进行插入排序,随后逐步缩小增量直至为1,最终完成整体排序。

常见的增量序列间隔选择方式

  1. Shell原始序列 :1 2 ... n / 4 n/4 n/4 n / 2 n/2 n/2 (n为原始数组长度)

  2. Hibbard序列 :1 3 7 ... 2 k − 1 2^k-1 2k−1

  3. Knuth序列 :1 4 13 ... ( 3 k − 1 ) / 2 (3^k-1)/2 (3k−1)/2

    最佳增量序列的的选择仍然是一个研究方向。

JavaScript实现

Shell序列

javascript 复制代码
function shellSort(list) {
    let n = list.length;
    let gap = n >> 1;
    while (gap) {
        // 分别处理以i开头,间隔gap的子序列
        for (let i = 0; i < gap; i++) {
            for (let j = i + gap; j < n; j += gap) {
                let k = j - gap;
                while (k >= 0 && list[k] > list[k + gap]) {
                    swap(list, k, k + gap);
                    k -= gap;
                }
            }
        }
        // 缩小gap
        gap = gap >> 1;
    }
    return list
}


for (let i = 0; i < 100; i++) {
    let list = generateList();
    console.log('origin list', list);
    let a = sort(clone(list)), b = shellSort(clone(list));
    console.log('sorte', a);
    console.log('shell', b);
    for (let j = 0; j < list.length; j++) if (a[j] !== b[j]) console.log('error');
    console.log('success')
}


// ---------------help----------------------

function clone(list) {
    return list.slice(0);
}

function swap(list, i, j) {
    var temp = list[i];
    list[i] = list[j];
    list[j] = temp;
}

function generateList() {
    let length = 10 + Math.ceil(Math.random() * 10);
    let list = [];
    while (length) {
        list.push(Math.ceil(Math.random() * 100));
        length--;
    }
    return list;
}

function sort(list) {
    list.sort((a, b) => a - b);
    return list;
}

Hibbard序列

javascript 复制代码
function shellSortByHibbard(list) {
    let n = list.length, K = Math.floor(Math.log2(n + 1));
    console.log('长度', n, 'K=', K);
    while (K) {
        let gap = Math.pow(2, K) - 1;
        // 分别处理以i开头,间隔gap的子序列
        for (let i = 0; i < gap; i++) {
            for (let j = i + gap; j < n; j += gap) {
                let k = j - gap;
                while (k >= 0 && list[k] > list[k + gap]) {
                    swap(list, k, k + gap);
                    k -= gap;
                }
            }
        }

        K--;
    }
    return list;
}

Knuth序列

javascript 复制代码
function shellSortByKnuth(list) {
    let n = list.length, K = Math.floor(Math.log(2 * n + 1) / Math.log(3));
    console.log('长度', n, 'K=', K);
    while (K) {
        let gap = (Math.pow(3, K) - 1) >> 1;
        // 分别处理以i开头,间隔gap的子序列
        for (let i = 0; i < gap; i++) {
            for (let j = i + gap; j < n; j += gap) {
                let k = j - gap;
                while (k >= 0 && list[k] > list[k + gap]) {
                    swap(list, k, k + gap);
                    k -= gap;
                }
            }
        }

        K--;
    }
    return list;
}
相关推荐
IT_陈寒7 小时前
Java空指针这次真把我坑惨了
前端·人工智能·后端
高级程序源8 小时前
django大学生创新创业项目管理系统94923-计算机课程设计、毕业设计
javascript·vue.js·spring boot·后端·python·django·课程设计
八荒启·交互动画8 小时前
# Web特效020—让 Web 特效真正动起来:时间循环应该怎么接
前端·webgl·网页特效·八荒启-交互动画·八荒启
动恰客流统计8 小时前
线下零售数字化浪潮下,客流统计的3个核心发展趋势
大数据·前端·人工智能
lizz22768 小时前
Babel插件手册
javascript
用户938515635078 小时前
从小米前端面试题,彻底搞懂闭包、作用域链与 useState 惰性初始化
前端·面试
粥里有勺糖9 小时前
视野修炼第133期 | Native 回春了?
前端·github·agent
aichitang20249 小时前
前端小skill
前端·人工智能·算法·ai·前端框架
前端·柱子10 小时前
q-floodfill白边锯齿?一招搞定抗锯齿边缘问题
前端·html·canva可画
葡萄城技术团队10 小时前
SpreadJS V19.2新特性揭秘:功能区键盘提示
前端