前端常见的排序算法算法

冒泡排序

我们先来了解一下冒泡排序算法,它是最慢的排序算法之一,但也是一种最容易实现的排
序算法。
之所以叫冒泡排序是因为使用这种排序算法排序时,数据值会像气泡一样从数组的一端漂浮到另一端。假设正在将一组数字按照升序排列,较大的值会浮动到数组的右侧,而较小的值则会浮动到数组的左侧。之所以会产生这种现象是因为算法会多次在数组中移动,比较相邻的数据,当左侧值大于右侧值时将它们进行互换。

代码实现

function swap(i,j,array){
  let temp = array[j];
  array[j] = array[i];
  array[i] = temp;
}

function bubbleSort(data) {
  let length = data.length, isSwap;
  for (var i = 0; i < length; i++) {            //正序
    isSwap = false;
    for (var j = 0; j < length - 1 - i; j++) {     //正序
      array[j] > array[j+1] && (isSwap = true) && swap(j,j+1,array);
    }
    if(!isSwap)
      break;
  }
  return data;
}

选择排序

我们接下来要看的是选择排序算法。选择排序从数组的开头开始,将第一个元素和其他元素进行比较。检查完所有元素后,最小的元素会被放到数组的第一个位置,然后算法会从第二个位置继续。这个过程一直进行,当进行到数组的倒数第二个位置时,所有的数据便完成了排序。
选择排序会用到嵌套循环。外循环从数组的第一个元素移动到倒数第二个元素;内循环从第二个数组元素移动到最后一个元素,查找比当前外循环所指向的元素小的元素。每次内循环迭代后,数组中最小的值都会被赋值到合适的位置

代码实现

function selectSort(data) {
    let length = data.length;
    let min = 0;
    for(let i = 0; i < length; i++){
        min = i;
        for(let j = i +1; j < length; j++){
            if(data[min] > data[j]){
                swap(min,j,data)
            }
        }
    }
  return data
}

插入排序

插入排序类似于人类按数字或字母顺序对数据进行排序。例如,让班里的每个学生上交一张写有他的名字、学生证号以及个人简介的索引卡片。学生交上来的卡片是没有顺序的,但是我想让这些卡片按字母顺序排好,这样就可以很容易地与班级花名册进行对照了。我将卡片带回办公室,清理好书桌,然后拿起第一张卡片。卡片上的姓氏是 Smith 。我把它放到桌子的左上角,然后再拿起第二张卡片。这张卡片上的姓氏是 Brown 。我把 Smith移右,把 Brown 放到 Smith 的前面。下一张卡片是 Williams ,可把它放到桌面最右边,而不用移动其他任何卡片。下一张卡片是 Acklin 。这张卡片必须放在这些卡片的最前面,因此其他所有卡片必须向右移动一个位置来为 Acklin 这张卡片腾出位置。这就是插入排序的排序原理。

代码实现

function insertSort(data) {
    let length = data.length;
    let index,current;
    for(let i = 0; i<length; i++){
        index = i;
        current = data[i];
        while(index>=0 && (data[index+1] < data[index])){
            swap(index, index+1, data);
            index--;
        }
    }
  return data
}

希尔排序

希尔排序是以它的创造者(Donald Shell)命名的。这个算法在插入排序的基础上做了很大的改善。希尔排序的核心理念与插入排序不同,它会首先比较距离较远的元素,而非相邻的元素。和简单地比较相邻元素相比,使用这种方案可以使离正确位置很远的元素更快地回到合适的位置。当开始用这个算法遍历数据集时,所有元素之间的距离会不断减小,直到处理到数据集的末尾,时算法比较的就是相邻元素了。
希尔排序的工作原理是,通过定义一个间隔序列来表示在排序过程中进行比较的元素之间有多远的间隔。我们可以动态定义间隔序列,不过对于大部分的实际应用场景,算法要用到的间隔序列可以提前定义好。有一些公开定义的间隔序列,使用它们会得到不同的结果。在这里我们用到了 Marcin Ciura 在他 2001 年发表的论文“Best Increments for theAverage Case of Shell Sort”(http:bit.ly/1b04YFv,2001)中定义的间隔序列。这个间隔序列是: 701, 301, 132, 57, 23, 10, 4, 1 。

代码实现

function shellsort(data) {
    let gap = Math.floor(data.length/2);
    while(gap>=1){
        for(let i = gap; i<data.length; i++){
            if(data[i]<data[i-gap]){
                swap(i-gap, i, data);
                shellTime += 1;
            }
        }
        gap = gap/2;
    }
  return data
}

归并排序

归并排序的命名来自它的实现原理:把一系列排好序的子序列合并成一个大的完整有序序列。从理论上讲,这个算法很容易实现。我们需要两个排好序的子数组,然后通过比较数据大小,先从最小的数据开始插入,最后合并得到第三个数组。然而,在实际情况中,归并排序还有一些问题,当我们用这个算法对一个很大的数据集进行排序时,我们需要相当大的空间来合并存储两个子数组。就现在来讲,内存不那么昂贵,空间不是问题,因此值得我们去实现一下归并排序,比较它和其他排序算法的执行效率。

代码实现

function mergeSort(data) {
    if(data.length < 2){
        return data
    }else{
        let mid = Math.floor(data.length/2);
        let left = data.slice(0, mid);
        let right = data.slice(mid);
        return merge(mergeSort(left), mergeSort(right));
    }
}
function merge(left, right) {
    let arr = [];
    while(left.length > 0 && right.length > 0){
        if(left[0] > right[0]) {
            arr.push(right.shift())
        }else{
            arr.push(left.shift())
        }
    }
    return arr.concat(left, right);
}

快速排序

快速排序是处理大数据集最快的排序算法之一。它是一种分而治之的算法,通过递归的方式将数据依次分解为包含较小元素和较大元素的不同子序列。该算法不断重复这个步骤直到所有数据都是有序的。
这个算法首先要在列表中选择一个元素作为基准值(pivot)。数据排序围绕基准值进行,将列表中小于基准值的元素移到数组的底部,将大于基准值的元素移到数组的顶部。

代码实现

function quickSort(data) {
    if(data.length === 0){
        return []
    }
    let lesser = [];
    let greater = [];
    let pivot = data[0];
    for(let i = 1; i<data.length; i++){
        if(data[i] < pivot){
            lesser.push(data[i]);
        }else{
            greater.push(data[i]);
        }
    }
    return quickSort(lesser).concat(pivot,quickSort(greater))
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351