排序笔记

记录学习排序的过程

1.冒泡排序

冒牌排序就是每次比较相邻的两个数的数值,前者如果比后者大就交换位置,一次遍历下来可以找出最大的数值,并且把它放在数组的最后。第二次遍历就找出次最大的项并且把它放到最后。如此循环...

function bubbleSort(array) {
    let len = array.length
    for(let i=0; i<len-1; i++) {
        for(let j=0; j<len-i-1; i++) {
            if(array[j] > array[j+1]) {
                [array[j], array[j + 1]] = [array[j + 1], array[j]]
            }
        }
    }
}
let arr = [56, 65, 1, 3, 5, 79, 13, 25, 63, 34, 388, 412, 65, 20, 22]
bubbleSort(arr)   // [1, 3, 5, 13, 20, 22, 25, 34, 56, 63, 65, 65, 79, 388, 412]

遍历的时候也可以反向遍历

function bubbleSort(array) {
    let len = array.length
    for(let i=len-1; i>=0; i--) {
        for(let j=0; j<i; j++) {
            if(array[j] > array[j+1]) {
                [array[j], array[j+1]] = [array[j+1], array[j]]
            }
        }
    }
}
let arr = [56, 65, 1, 3, 5, 79, 13, 25, 63, 34, 388, 412, 65, 20, 22]
bubbleSort(arr)   // [1, 3, 5, 13, 20, 22, 25, 34, 56, 63, 65, 65, 79, 388, 412]

冒泡排序的效率及稳定性

  • 对于n项的数组,要比较(n-1)+(n-2)+...+1 = n*(n-1)/2次,所以大O法表示时间复杂度:O(n2)
  • 从稳定性上来看,排序前值相同的两个元素的相对位置在排序后不改变,所以冒泡排序是稳定的。

2.选择排序

选择排序与冒泡排序有相似之处,选取一个元素与后面的元素一次比较,一次遍历之后可以找到最小的那个元素,数次遍历之后排序完成。

function selectSort(arr) {
    let len = arr.length
    for(let i=0; i<len-1; i++) {
        for(let j=i+1; j<len; j++) {
            if(arr[j] < arr[i]) {
                [arr[i], arr[j]] = [arr[j], arr[i]]
            }
        }
    }
}
let array = [10,2,13,5,26,799,1,33,21,51]
selectSort(array)  //[1, 2, 5, 10, 13, 21, 26, 33, 51, 799]

选择排序的效率及稳定性

  • 选择排序的交换次数是O(n),但是比较次数还是O(n2),所以时间复杂度还是O(n2)
  • 稳定性来看,假设当前元素在后续项中找到最小值并与之交换,但是该最小值的前一项的值与当前值相等,此时稳定性被破坏,所以选择排序是不稳定的。例子如下:
[5(a), 7, 6, 5(b), 1, 3]  --> [1, 7, 6, 5(b), 5(a), 3]
为了区分两个相同的项,在它们后面加上a,b以区分。显然,5(a)位于5(b)前面。
假设当前项为5(a),在第一轮遍历中找到最小值1,并且与之交换。
交换后可以看到,5(a)在5(b)的后面,它们两个的相对位置发生了变换,不符合稳定性。

3.插入排序

插入排序就是在数组中取出某一元素,把该元素之前的序列视为已经排好序的序列,再拿当前的数与前面有序的数列的项比较,找到准确的位置进行赋值。

function insertSort(array) {
    let len = array.length
    for(let i=1; i<len; i++) {
        let j, temp = array[i]  //记录当前值
        for(j=i-1; j>=0 && array[j]>temp; j--) {  //判断当前值与之前面的数的数值关系
            array[j+1] = array[j]  //如果当前值小于前面的值,把前面大的值赋值给当前值
        }
        array[j+1] = temp  //最后把当前的值放进去对应的位置
    }
}
let arr = [6,12,4,1,13,22,26,20,14,33,7,9]
insertSort(arr)  //[1, 4, 6, 7, 9, 12, 13, 14, 20, 22, 26, 33]
  • 示例如下


    示例.png

插入排序的效率及稳定性

  • 第一趟最多1次比较,第二趟最多2次比较,以此类推,最后一趟是n-1次
  • 1 + 2 + 3 + ... + n-1 = n*(n - 1) / 2
  • 每次插入前,平均只有一般数据需要比较,所以 n*(n-1)/4,相对于其他排序,比较次数少一半,但还是O(n2)
  • 插入排序是稳定的,如果A在有序的序列内,如果B与A一样,B会被放到A的后面
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、排序简介 我们通常所说的排序算法往往指的是内部排序算法,即数据记录在内存中进行排序。 排序算法大体可分为两种:...
    小碧小琳阅读 3,757评论 0 1
  • 一、排序简介 我们通常所说的排序算法往往指的是内部排序算法,即数据记录在内存中进行排序。 排序算法大体可分为两种:...
    小碧小琳阅读 4,077评论 0 1
  • 冒泡排序: 原理:遍历数组,前一个和后一个进行比较,如果大于后边的,就交换数值,数组遍历了a.length-1次,...
    115小小五阅读 2,839评论 0 4
  • 内排序:指在排序期间数据对象全部存放在内存的排序。 外排序:指在排序期间全部对象太多,不能同时存放在内存中,必须根...
    是凸凸不是凹凹阅读 2,662评论 0 0
  • 六、归并排序 参考归并排序 最易于理解的白话:首先考虑下如何将将二个有序数列合并 1、这个非常简单,只要从比较二个...
    小碧小琳阅读 4,662评论 0 1