排序算法-N个正整数排序

算法

高德纳在《计算机程序设计艺术》里对算法归纳为以下几点:

  1. 输入: 一个算法必须有零或以上的输入量
  2. 输出: 一个算法应有一个或以上的输出量
  3. 明确性: 算法的描述必须无歧义,实际运行结果是确定的
  4. 有限性: 必须在有限个步骤内结束
  5. 有效性: 又称可行性,能够被执行者实现

如果想详细研究算法推荐《数据结构与算法分析》

数据结构与算法分析

定义问题

数组array含有N个正整数
输入量为array
请将array中的数字从小到大排列
输出量为排好序的数组

代码例子

var array = [5,2,4,6,8]
function sort(){
   你的代码
}
sort(array) === [2,4,5,6,8]

当你遇到思路障碍怎么办?

  • 抽象的问题转化为具体的问题
  • 没见过的问题转化为见过的问题

排序算法

所有算法都可在此查看演示

冒泡排序(BUBBLE)

重复地比较要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。比较数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。每比较一整轮,最大的都会出现在最后故名---冒泡排序

流程如下:

  1. 我们拿到一个数组


    数组
  2. 开始从前两个开始比较,发现44>3,所以不用交换


    比较
  3. 接着往后比较,发现38<44,所以交换他们两个的位置


    比较
  4. 以此类推直到第一轮结束,我们得到了最大的那一个----50(冒的第一个泡)
    第一轮结束
  5. 接着下一轮,又从头开始两个两个地比较,重复第一轮,我们就得到了第二个最大的------48
    第二轮结束
  6. 如此进行多轮比较我们会得到一个从小到大的数组


    从小到大
  7. 代码实现:
function bubbleSort(array) {
    for (let i = 0; i < array.length - 1; i++) {
        for (let j = 0; j < array.length - i - 1; j++) {
            if (array[j] > array[j + 1]) {
                let temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}

2. 选择排序(SELECT)

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
流程如下:

  1. 拿到一个数组


    数组
  2. 我们要选出这个数组中最小的元素然后把它和第一个数交换(放到最前面),所以我们先认为3为最小,然后和后面的数依次进行比较.


    和最小值比较
  3. 当比到2的时候,我们发现3>2,所以我们就认为2为最小值,后面的数应该都和2进行比较.


    改变最小值的元素
  4. 当比较完所有的元素,确定2为最小值的时候,把最小值也就是2与第一个元素的位置互换.


    互换位置
  5. 然后从第二个元素开始新一轮的比较,过程和第一轮一样.把44看做最小值和后面的元素进行比较.


    第二轮
  6. 经过多轮比较得到从小到大的数组.


    从小到大
  7. 代码实现
function selectSort(arr) {
    var minIndex, temp;
    for (let i = 0; i < arr.length - 1; i++) {
        minIndex = i; // 先把第一个看做最小值
        for (let j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    return arr;
}

3, 插入排序(INSERT)

将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序。是稳定的排序方法。
流程如下:

  1. 拿到一个数组


    数组
  2. 把第一个元素看做一个新数组,然后把第二个元素依次和新数组的元素进行比较(虽然只有一个...),然后插入到适当的位置.


    与新数组的元素进行比较

    插入到适当的位置
  3. 然后以此类推,把前两个元素看做是一个新数组,然后把第三个元素依次与新数组进行比较,然后插入到适当的位置.


    比较

    插入适当的位置
  4. 把剩下的元素依次插入,最后得到从小到大排列的数组.


    从小到大
  5. 代码实现
function insertionSort(array) {

    for (let i = 1; i < array.length; i++) {
        let key = array[i];
        let j = i - 1;
        while (j >= 0 && array[j] > key) {
            array[j + 1] = array[j];
            j--;
        }
        array[j + 1] = key;
    }
    return array;
}

4. 归并排序(MERGE)

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
流程如下:

  1. 拿到一个数组


    数组
  2. 我们把数组平均分成左右两部分,得到两个新数组,然后再把每个数组平均分成两部分,一直分到每个数组只有两个元素,然后比较第一组


    比较第一组
  3. 因为3<44所以位置不变然后比较第二组,因为38>5所以调换位置.


    图片.png
  4. 重点来了,这个时候先不着急比较第三组而是把排好序的一二两组放在一起排序.


    图片.png
  5. 之后就是比较第三组和第四组,然后同样把他们放在一起排好序.


    图片.png
  6. 然后并不是比较第五组和第六组,而是把第一组和第二组产生的新数组和,第三组和第四组产生的新数组放在一起排序成为新数组.


    图片.png
  7. 同样把剩下的按以上步骤重来一遍.我们得到两个排好序的数组.然后给这两个数组排序就完成了.


    图片.png

    排序后:


    图片.png
  8. 代码实现
function mergeSort(arr) {
    var len = arr.length;
    if (len < 2) {
        return arr;
    }
    var middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right) {
    var result = [];

    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }

    while (left.length)
        result.push(left.shift());
    while (right.length)
        result.push(right.shift());

    return result;
}

5. 快速排序

每个元素找到自己对应的位置(前面的都比我小,后面的都比我大)
流程如下:

  1. 拿到一个数组


    数组
  2. 拿第一个元素和后面的元素进行比较,找出所有比第一个元素小的元素,放在第一个元素的右边然后把第一个元素与这些比他小的元素的最后一个互换.


    只有2比3小

    互换
  3. 前两个元素的位置已经没错了,然后以第三个元素为标准,和后面的元素进行比较.


    比较之后
  4. 把比他小的元素放在他的右边(绿色),然后让它和绿色的最后一个交换位置.


    交换位置
  5. 然后从左边没有确定位置的元素(非橙色)开始以上步骤----也就是19


    从19开始
  6. 一直到所有元素的位置都正确.


    都有了正确的位置
  7. 代码实现
function quickSort(array) {
    function quick(array, left, right) {
        let index;
        if (array.length > 1) {
            index = partition(array, left, right);
            if (left < index - 1) {
                quick(array, left, index - 1);
            }
            if (index < right) {
                quick(array, index, right);
            }
        }
        return array;
    }
    function partition(array, left, right) {
        const pivot = array[Math.floor((right + left) / 2)];
        let i = left;
        let j = right;
    
        while (i <= j) {
            while (array[i] < pivot) {
                i++;
            }
            while (array[j] > pivot) {
                j--;
            }
            if (i <= j) {
                [array[i], array[j]] = [array[j], array[i]]
                i++;
                j--;
            }
        }
        return i;
    }
    quick(array, 0, array.length - 1);
};

6. 随机快速排序

顾名思义,就是在快速排序的基础上,加入随机的机制.
在快速排序的时候我们是从左到右来选取比较对象,在随机快速排序中我们是随机来选取对象.
流程如下:

  1. 拿到一个数组


    数组
  2. 随机选择一个元素.


    随机选择到了44
  3. 并且把比他小的放在他的右边


    把比他小的先放在他的右边
  4. 然后把他和比他小的最右边的元素交换位置


    交换位置
  5. 然后在随机选一个元素,重复步骤,知道所有元素都是在正确的位置上.


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

推荐阅读更多精彩内容

  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,159评论 0 52
  • 数据结构与算法--排序之冒泡、选择、插入、希尔 我们关注的主要对象是重新排列数组元素的算法,每个元素都有一个主键,...
    sunhaiyu阅读 1,118评论 2 12
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,726评论 0 15
  • 概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的...
    Luc_阅读 2,253评论 0 35
  • 排序的基本概念 在计算机程序开发过程中,经常需要一组数据元素(或记录)按某个关键字进行排序,排序完成的序列可用于快...
    Jack921阅读 1,416评论 1 4