希尔排序

希尔排序

概述

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

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

  1. Shell原始序列 :1 2 ... <math xmlns="http://www.w3.org/1998/Math/MathML"> n / 4 n/4 </math>n/4 <math xmlns="http://www.w3.org/1998/Math/MathML"> n / 2 n/2 </math>n/2 (n为原始数组长度)

  2. Hibbard序列 :1 3 7 ... <math xmlns="http://www.w3.org/1998/Math/MathML"> 2 k − 1 2^k-1 </math>2k−1

  3. Knuth序列 :1 4 13 ... <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 3 k − 1 ) / 2 (3^k-1)/2 </math>(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;
}
相关推荐
im_AMBER4 小时前
告别“玄学”UI:从“删代码碰运气”到“控制 BFC 结界”
前端·css
bjzhang754 小时前
使用 HTML + JavaScript 实现文件树
javascript·html·文件树
千寻girling4 小时前
《 MongoDB 教程 》—— 不可多得的 MongoDB
前端·后端·面试
攀登的牵牛花4 小时前
前端向架构突围系列 - 状态数据设计 [8 - 3]:服务端状态与客户端状态的架构分离
前端
掘金安东尼4 小时前
⏰前端周刊第 452 期(2026年2月2日-2月8日)
前端·javascript·github
古茗前端团队4 小时前
业务方上压力了,前端仔速通RGB转CMYK
前端
ArkPppp5 小时前
NestJS全栈实战笔记:优雅处理 Entity 与 DTO 的映射与字段过滤
javascript·nestjs
广州华水科技5 小时前
单北斗变形监测一体机在基础设施安全与地质灾害监测中的应用价值分析
前端
钟智强5 小时前
React2Shell:CVE-2025-66478 Next.js 远程执行漏洞深度分析与代码剖析
开发语言·javascript·ecmascript
Dragon Wu5 小时前
Electron Forge集成React Typescript完整步骤
前端·javascript·react.js·typescript·electron·reactjs