JavaScript排序算法

选择排序

基本思想

将待排序数组中最小的那个数放置于序列首位,之后将数组中的剩余元素中最小的取出放置于序列末尾,之后进行递归操作,直至待排序数组中没有元素。

算法实现

let selectsort = arr => { 
    if (arr.length <= 0) {return [];} 
    let min = Math.min.apply(null, arr);
    let minindex = arr.indexOf(min);
    arr.splice(minindex, 1);
    return [min].concat(arr.length > 1 ? selectsort(arr):arr); 
}

快速排序

基本思想

将原数组分为左和右两部分,进行一次排序确保其中一部分(左或右)中的所有数比另一部分中的都要小。之后继续对左右两部分进行递归,直到分片数组长度为1时退出递归,继续分组排序,直到所有递归完成时排序完成。

算法实现

let quicksort = (numbers, head, tail) => { 
    if (head >= tail || numbers === null || numbers ===undefined || numbers.length <= 1) {
        return;
    }
    let i = head;
    let j = tail;
    let pivot = numbers[Math.floor((head + tail) / 2)];
    while (i <= j) { 
        while (numbers[i] < pivot) {
            ++i;
        }
        while (numbers[j] > pivot) {
            --j;
        }
        if (i < j) {
            let swap = numbers[i];
            numbers[i] = numbers[j];
            numbers[j] = swap;
            ++i;
            --j;
        } else if (i == j) {
            ++i;
        }
    }
    quicksort(numbers, head, j);
    quicksort(numbers, i, tail);
    return numbers;
}

阮一峰版本

可以通过新增空数组的方式,避免交换顺序。

let quickSort = arr => {
    if (arr.length <= 1) { return arr; }
    let pivotIndex = Math.floor(arr.length / 2);
    let pivot = arr.splice(pivotIndex, 1)[0];
    let left = [];
    let right = [];
    for (let i = 0; i < arr.length; i++){
    if (arr[i] < pivot) { left.push(arr[i])
    } else { right.push(arr[i]) }
    }
    return quickSort(left).concat(
    [pivot], quickSort(right) )
    }

归并排序

基本思想

先将数组分解成大小为1的各个部分(不停地二等分直至大小为1),然后从左至右依次进行排序将集合归并(从前至后依次比较要待归并的两个集合的首元素,将小的元素放入新队列并在待归并的集合中移除该元素)。

算法实现

let mergesort = arr => {
    let n = arr.length;
    if (n <= 1) { return arr }
    let left = arr.slice(0, Math.floor(n / 2));
    let right = arr.slice(Math.floor(n / 2));
    return merge(mergesort(left), mergesort(right));
}


let merge = (a, b) => { 
    if (a.length <= 0) { return b; }
    if (b.length <= 0) { return a; }
    return a[0] > b [0] ? [b[0]].concat(merge(a,b.slice(1))) : [a[0]].concat(merge(b,a.slice(1)))
}

计数排序

基本原理

常用于一定范围内的数,用一个哈希表记录数组中元素的个数,记录完成后按从小到大的顺序遍历哈希表(需要最小值和最大值,可取0 至 max),输出排序后的数组。

算法实现

let countsort = arr => {
    let hashTable = {}, max = 0, result = []
    for (let i = 0; i < arr.length; i++) { 
        arr[i] in hashTable ? hashTable[arr[i]] += 1 : hashTable[arr[i]] = 1;
        if (arr[i] > max) { max = arr[i] }
    }
    //遍历hashTable,最小值为0,最大值为max
    for (let i = 0; i <= max; i++) {
        if (i in hashTable) {
            while (hashTable[i]--> 0) {
                result.push(i);
            }
        }
    }
    return result;
}    

冒泡排序

基本思想

重复的遍历数组,比较连续的两个元素,如果顺序错误就交换,直到最后一次遍历中没有任何连续的两个元素需要交换,排序完成。

算法实现

暴力写法
let bubblesort = arr => { 
    let continuing = true;
    while (continuing) { 
        continuing = false;
        let swap;
        for (let j = 0; j < arr.length-1; j++) { 
            if (arr[j] > arr[j + 1]) {
                swap = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = swap;
                continuing = true;
            }
        }
    }
    return arr;
}

优化写法

由于每次内层循环结束后,最大的数一定会被交换到最右边,所以第n-i次冒泡可以只执行i次运算(从右往左的n-i个元素必为从大到小,因此不参与冒泡)

let bubblesort = arr => { 
    for (let i = 0; i < arr.length-1;i++){ 
        let swap;
        for (let j = 0; j < arr.length-1-i; j++) { 
            if (arr[j] > arr[j + 1]) {
                swap = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = swap;
            }
        }
    }
    return arr;
}

插入排序

基本思想

从数组第二个元素开始将当前元素与左侧的元素进行比较,并将当前元素插入合适的位置(对于左侧元素,从右至左依次冒泡),直到插入原数组最后一个元素后排序完成。

算法实现

let inssort = arr => { 
    let n = arr.length - 1;
    let swap;
    for (let i = 1; i < n; i++) { 
        for (let j = i; j >= 0; j--){
            if (arr[j] < arr[j-1]) {
                swap = arr[j];
                arr[j] = arr[j-1];
                arr[j-1] = swap;
            }
        }
    }
    return arr;
}

希尔排序

基本思想

希尔排序通过将比较的全部元素按相同间隔(即gap:数组长度不断除以2(向下取整))分为几个区域,对于每个区域采用插入排序,每个区域排序完成后减少区域的个数(缩小区域的间隔直到为1),由此来提升插入排序的性能。(例如,数组[1,2,3,4,5] 初始间隔为5/2 向下取整=2,第一次数组分为[1,3,5]和[2,4] 下一次的间隔为2/2 =1,数组分为[1,2,3,4,5])。

算法实现

let shellsort = arr => {
    for (let gap = Math.floor(arr.length / 2); gap >= 1; gap = Math.floor(gap / 2)) {
        for (let i = gap; i < arr.length; i++) {
            let swap = arr[i];
            let j;
            for (j = i - gap; j >= 0 && arr[j] > swap; j -= gap) {
                arr[j + gap] = arr[j];
            }
            arr[j + gap] = swap;
        }
    }
    return arr;
}

基数排序

基本思想

将整数按位数切割成不同的数字(从个位至最大位数),然后按每个位数分别比较。

  1. 例如数组[1,7,3,25,33],先新建余数为0-9的10个数组buckets[0-9],来存放对位数取余数为0-9的数;以及一个空数组来存放排序后的元素,将原数组全部放入buckets数组后,按余数从小到大依次放入新增的空数组(存放排序后的元素)。
  2. 第一次结果为个位数小的排在前面,变成[1,3,33,25,7]
  3. 第二次结果为十位数小的在前面,变成[1,3,7,25,33],因为最大位数为2,此时排序完成。

算法实现

let radixsort = arr => {
    const max = Math.max.apply(null, arr);
    let digit = `${max}`.length;
    let buckets = [];
    let start = 1;
    while (digit > 0) {
        start *= 10;
        for (let i = 0; i < arr.length; i++) {
            const index = arr[i] % start;
            !buckets[index] && (buckets[index] = []);
            buckets[index].push(arr[i]);
        }
        arr = [];
        for (let i = 0; i < buckets.length; i++) {
            buckets[i] && (arr = arr.concat(buckets[i]));
        }
        buckets = [];
        digit--;
    }
    return arr;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 写在前面 个人感觉:javascript对类似排序查找这样的功能已经有了很好的封装,以致于当我们想对数组排序的时候...
    faremax阅读 467评论 0 1
  • 排序算法: 冒泡排序:频繁交换 ,找出其中最大的放到最后一个 一次找到第二大的放大倒数第二个...最后完成 选择排...
    小螃蟹_5f4c阅读 708评论 0 1
  • 在我们的日常生活中,排序是经常会被使用到的,因此排序算法也会广泛的应用到解决日常问题上面。所有的排序算法已经上传到...
    kim_jin阅读 418评论 0 3
  • 数据结构和算法本身解决的是“快”和“省”的问题,即如何让代码运行得更快,如何让代码更省存储空间。所以,执行效率是算...
    WEB前端含光阅读 274评论 0 0
  • 虽然前端对于算法的要求并不高,但是工作和面试偶尔还是会遇到排序算法和二分查找法。笔者通过这篇文章对排序和查找简单总...
    Lee_YJ阅读 446评论 0 1