说明
对数组进行 冒泡排序 算是比较简单的,冒泡排序也是容易理解的一种排序算法了,在面试的时候,很可能就会问到。
实现原理
数组中有n
个数,比较每相邻两个数,如果前者大于后者,就把两个数交换位置;这样一来,第一轮就可以选出一个最大的数放在最后面;那么经过n-1
(数组的 length - 1) 轮,就完成了所有数的排序。
好的,我们先来实现找数组中的最大数,并把他放到数组最后。
var arr = [3,4,1,2];// 遍历数组,次数就是arr.length - 1for (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 - 1for (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
,是不是合适呢?
i < arr.length - 1 -j
,才合适,看下面的代码。 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)
时间复杂度指的是一个算法执行所耗费的时间
空间复杂度指运行完一个程序所需内存的大小稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面不稳定指,如果a=b,a在b的前面,排序后可能会交换位置总结
1、外层 for 循环控制循环次数
2、内层 for 循环进行两数交换,找每次的最大数,排到最后3、设置一个标志位,减少不必要的循环好的,下一篇文章,来实现下冒泡排序的可视化,把冒泡排序的过程展示出来。