天天看点

冒泡排序,快速排序,插入排序的总结

1.冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

如图演示:

冒泡排序,快速排序,插入排序的总结

 代码:

//声明一个数组

var arr=[6,3,5,4,2,8];

function bubbleSort(arr){

//max为从左到右,两个数进行比较的次数(遍历数组,次数就是arr.length-1)

 var max=arr.length-1;

 for(var j=0;j<max;j++){

   var done=true;

   for(var i=0;j<max-j;i++){

//两个数进行比较,如果arr[i]>arr[i+1]则两个数交换位置

     if(arr[i]>arr[i+1]){

        var temp=arr[i];

        arr[i]=arr[i+1];

        arr[i+1]=temp;

        done=false;

}

}

if(done){

  break;

}

}

return arr;

}

bubbleSort(arr);

运行结果为[2,3,4,5,6,8]

2.快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

如图演示

冒泡排序,快速排序,插入排序的总结

 代码:

var arr=[5,7,2,9,3,8,4,7,1];

// 每次选择最左边的数作为基数

function quickSort(arr){

  if (arr.length<2) { return arr; }

  // 定义左指针

  var left=0;

  // 定义右指针

  var right=arr.length-1;

  //开启每一轮的排序

  while(left<right){

    // 寻找右边比arr[0]小的数的下标

    while(arr[right]>=arr[0] && left<right){

      right=right-1;

    }

    // 寻找左边比arr[0]大的数的下标

    while(arr[left]<=arr[0] && left<right){

      left++;

    }

    //当左边指针与右边指针相遇后,交换arr[0]与当前两个指针所在的元素

    if (right==left) {

      let mid=arr[right];

      arr[right]=arr[0];

      arr[0]=mid;

      break;

    }

    // 当左指针小于右指针的位置,交换两个指针当前位置的元素

    let tem=arr[right];

    arr[right]=arr[left];

    arr[left]=tem;

  }

  //递归实现

  return quickSort(arr.slice(0,left)).concat(arr.slice(left,right+1)).concat(quickSort(arr.slice(right+1)));

运行结果为:[

  1, 2, 3, 4, 5,

  7, 7, 8, 9

]

3.插入排序的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

如图所示:

冒泡排序,快速排序,插入排序的总结

插入排序的思路跟整理扑克牌是一样的,即每次拿到一张牌,按大小顺序将其插入到合适的位置。那么插入排序实际上就是:每次将一个数插入到有序的数组中去(初始一个数字自然有序)。

下面以实例结合代码来分析一个插入排序的过程:

冒泡排序,快速排序,插入排序的总结

由于第一个数 6 是自然有序的,所以我们从第二个数 5 开始考察, 将 5 取出与它的前一个数 6 比较,5 < 6, 将 6 复制到 5 的位置,5 向前移动继续比较,此时 5 已经处于数组第一位,第一次排序结束,将 5 放入当前位置;

冒泡排序,快速排序,插入排序的总结

此时 [5, 6] 已经构成有序数组,考察 4,将 4 取出与它的前一个数 6 比较,4 < 6,将 6 复制到 4 的位置;4 向前移与 5 比较,4 < 5,将 5 复制到前一个 6 的位置,此时 4 处于数组第一位,第二趟排序结束。

冒泡排序,快速排序,插入排序的总结

后面的排序过程与前面分析的过程一致,总结一下就是:不断将大于当前考察对象的数后移一位,直到找到考察对象应该处于的位置。有一个需要注意的点是,考察对象不一定是要一直向前移动到数组第一个位置才结束一趟排序,如果中间找到了合适的位置,这趟排序是可以提前终止的。

举例:

冒泡排序,快速排序,插入排序的总结

这一点正是插入排序的精髓所在!如果对一个已经有序的数组使用插入排序,插入排序只会遍历数组一遍,时间复杂度退化为 O(n);可以想象,如果对一个接近有序的数组使用插入排序,其效率是非常可观的,而很多时候我们处理的数据是接近有序的,只需调整一些无序项,所以插入排序是很有用的。

代码:

function insertSort(arr) {

  let length = arr.length;

  for(let i = 1; i < length; i++) {

    let temp = arr[i];

    let j = i;

    for(; j > 0; j--) {

      if(temp >= arr[j-1]) {

        break;      // 当前考察的数大于前一个数,证明有序,退出循环

      }

      arr[j] = arr[j-1]; // 将前一个数复制到后一个数上

    }

    arr[j] = temp;  // 找到考察的数应处于的位置

  }

  return arr;

}

// example

let arr = [2,5,10,7,10,32,90,9,11,1,0,10]

console.log(insertSort(arr));

继续阅读