JavaScript实现冒泡排序

说明

对数组进行 冒泡排序 算是比较简单的,冒泡排序也是容易理解的一种排序算法了,在面试的时候,极可能就会问到。前端

实现原理

数组中有 n 个数,比较每相邻两个数,若是前者大于后者,就把两个数交换位置;这样一来,第一轮就能够选出一个最大的数放在最后面;那么通过 n-1(数组的 length - 1) 轮,就完成了全部数的排序。

图片描述

好的,咱们先来实现找数组中的最大数,并把他放到数组最后。面试

var arr = [3,4,1,2];
// 遍历数组,次数就是arr.length - 1
for (var i = 0; i < arr.length - 1; i++) {
    // 若是前一个数 大于 后一个数 就交换两数位置
    if (arr[i] > arr[i + 1]) {
        var temp = arr[i];
        arr[i] = arr[i + 1];
        arr[i + 1] = temp;
    }
}
console.log(arr)  // [3, 1, 2, 4]

咱们能找到数组中最大的数,放到最后,这样重复 arr.length - 1 次,即可以实现数组按从小到大的顺序排好了。算法

var arr = [3,4,1,2];
// 遍历数组,次数就是arr.length - 1
for (var j = 0; j < arr.length - 1; j++) {
    // 这里 i < arr.length - 1 ,要思考思考合适吗?咱们下面继续说
    for (var i = 0; i < arr.length - 1; i++) {
        if (arr[i] > arr[i + 1]) {
            var temp = arr[i];
            arr[i] = arr[i + 1];
            arr[i + 1] = temp;
        }
    }
}
console.log(arr)  // [1,2,3,4]

虽然上面的代码已经实现冒泡排序了,但就像注释中提到的,内层 for 循环的次数写成,i < arr.length - 1 ,是否是合适呢?
咱们想一下,当第一次,找到最大数,放到最后,那么下一次,遍历的时候,是否是就不能把最后一个数算上了呢?由于他就是最大的了,不会出现,前一个数比后一个数大,要交换位置的状况,因此内层 for 循环的次数,改为 i < arr.length - 1 -j ,才合适,看下面的代码。segmentfault

var arr = [3, 4, 1, 2];
function bubbleSort (arr) {
  for (var j = 0; j < arr.length - 1; j++) {
    // 这里要根据外层for循环的 j,逐渐减小内层 for循环的次数
    for (var i = 0; i < arr.length - 1 - j; i++) {
      if (arr[i] > arr[i + 1]) {
        var temp = arr[i];
        arr[i] = arr[i + 1];
        arr[i + 1] = temp;
      }
    }
  }
  return arr;
}
bubbleSort(arr);

咱们想下这个状况,当原数组是,
arr = [1,2,4,3];
在通过第一轮冒泡排序以后,数组就变成了
arr = [1,2,3,4];
此时,数组已经排序完成了,可是按上面的代码来看,数组还会继续排序,因此咱们加一个标志位,若是某次循环完后,没有任何两数进行交换,就将标志位 设置为 true,表示排序完成,这样咱们就能够减小没必要要的排序,提升性能。数组

完整代码

var arr = [3, 4, 1, 2];
function bubbleSort (arr) {
  var max = arr.length - 1;
  for (var j = 0; j < max; j++) {
    // 声明一个变量,做为标志位
    var done = true;
    for (var i = 0; i < max - j; i++) {
      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);

性能

时间复杂度: 平均时间复杂度O(n*n) 、最好状况O(n)、最差状况O(n*n)
空间复杂度: O(1)
稳定性:稳定性能

时间复杂度指的是一个算法执行所耗费的时间
空间复杂度指运行完一个程序所需内存的大小
稳定指,若是a=b,a在b的前面,排序后a仍然在b的前面
不稳定指,若是a=b,a在b的前面,排序后可能会交换位置spa

总结

一、外层 for 循环控制循环次数
二、内层 for 循环进行两数交换,找每次的最大数,排到最后
三、设置一个标志位,减小没必要要的循环code

好的,下一篇文章,来实现下冒泡排序的可视化,把冒泡排序的过程展现出来。
JavaScript实现冒泡排序 可视化blog

前端简单说