排序算法——冒泡、选择、插入排序

809 阅读2分钟

这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战

排序算法——简单排序

一、 冒泡排序

冒泡排序的实现

相比其他排序的运行效率较低,但是冒泡排序是排序算法中最简单的;

  • 对未排序的各元素从头到尾一次比较相邻的两个元素大小关系

  • 比如说从小到大排序;第一个和第二个元素进行比较,如果第一个比第二个大的话,两者就交换位置,接着第二个和第三个进行比较,依次比较到最后一个;

    for (var j = 0; j < i; j++) {
        if (this.array[j] > this.array[j + 1]) {
            var temp = this.array[j];
            array[j] = array[j+1];
            array[j+1] = temp;
        }
    }
    
  • 在第一轮进行比较的时候就会把那个最大的元素移动到最后一位,第二轮的时候就把次大元素移动到倒数第二位,以此类推;

    也就是说,在第n轮中我们需要比较length-n-1次,所以上面这个循环还要在外面再嵌套一个循环;每一轮最后一个那个都是最大的,所以每一轮之后比较次数都会减少一次;

    for (var i = length - 1; i >= 0; i--) {
        ......
    }
    

也就是说,冒泡排序对于n个数据的比较次数为n*(n-1)/2次;交换次数大概是n*(n-1)/4次,用大O表示法为O(N^2)

二、选择排序

选择排序改进了冒泡排序,将交换的次数由O(n^2)减少到O(n); 以从小到大排序为例,

  • 通过索引值处理

  • 对未排序的元素从头到尾遍历,得到最小值,让最小值和第一个元素交换位置

    for (var j = min + 1; j < length; j++) {
            if (array[min] > array[j]) {
                min = j
            }
        }
    swap(min, j);
    
  • 接下来从第二个元素开始遍历,同样取到最小值,让这一次的最小值跟第二个元素交换位置,以此类推;

    for (var i = 0; i < length - 1; i++) {
        var min = i;
        ......
    }
    

选择排序的比较次数和冒泡排序一样,都是O(N^2),但是选择排序的交换次数是O(N)(交换n-1次即可);所以选择排序通常认为执行效率是高于冒泡排序的;

三、插入排序

插入排序是简单排序中效率最高的,也是学习其他高级排序的技术,比如希尔排序、快速排序;插入排列的实现核心是局部有序;以从小到大为例

  • 从第一个元素开始,这个元素可以认为已经被排序
  • 取出下一个元素,在已经排序的元素中从后往前扫描
  • 如果该已排序元素大于新元素,就将该元素移到下一位置,重复该步骤直到找到一个已排序元素小于或等于新元素的位置;
  • 将新元素插入到该位置后,重复上面的步骤;

我们需要从头到尾对数组的每一项进行排序,因此外层循环就是遍历数组的每一项;取出每一项之后,将这一项跟前面各项(从尾到头)进行比较,如果较大就跳出while循环;

for (var i = 0; i < length; i++) {
    var temp = this.array[i];
    var j = i;
    while (this.array[j - 1] > temp && j > 0) {
        this.array[j] = this.array[j - 1];
        j--;
    }
    this.array[j] = temp;
}

插入排序我们最多需要的比较次数N*(N-1)/2次,跟上面两个方法是一样的,但是插入排序的平均比较次数其实是N*(N-1)/4次;注意:排序算法的比较次数是选择排序的一半,这个算法的效率是高于选择排序的;

也可以分别执行一下,看看它们的执行时间比较得出哪一个效率高;