希尔排序

希尔排序

概述

希尔排序是插入排序的改进版,也称缩小增量排序。其核心思想是将原始数组按增量分成多个子序列,对每组进行插入排序,随后逐步缩小增量直至为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;
}
相关推荐
故事与九8 分钟前
vue3使用vue-pdf-embed实现前端PDF在线预览
前端·vue.js·pdf
小西↬9 分钟前
vite+vue3+websocket处理音频流发送到后端
javascript·websocket·音视频
Mintopia1 小时前
🚀 顶点-面碰撞检测之诗:用牛顿法追寻命运的交点
前端·javascript·计算机图形学
wb1891 小时前
企业WEB应用服务器TOMCAT
运维·前端·笔记·tomcat·云计算
烛阴1 小时前
解锁 Gulp 的潜力:高级技巧与工作流优化
前端·javascript
Entropy-Lee2 小时前
JavaScript 语句和函数
开发语言·前端·javascript
Wcowin3 小时前
MkDocs文档日期插件【推荐】
前端·mkdocs
xw53 小时前
免费的个人网站托管-Cloudflare
服务器·前端
网安Ruler4 小时前
Web开发-PHP应用&Cookie脆弱&Session固定&Token唯一&身份验证&数据库通讯
前端·数据库·网络安全·php·渗透·红队
!win !4 小时前
免费的个人网站托管-Cloudflare
服务器·前端·开发工具