冒泡排序就是相邻的两个数进行比较,将大的放在后面,小的放在前面。换句话说就是,前面的数比后面的数大,就交换位置,否则不换位置,图解:以数组
51 | 56 | 45 | 5 | 86 | 54 |
第一趟排序
第一次:51和56比较,不交换位置
51 | 56 | 45 | 5 | 86 | 54 |
第二次:56和45比较,交换位置
51 | 45 | 56 | 5 | 86 | 54 |
第三次:56和5比较,交换位置
51 | 45 | 5 | 56 | 86 | 54 |
第四次:56和86比较,不交换位置
51 | 45 | 5 | 56 | 86 | 54 |
第五次:86和54比较,交换位置
51 | 45 | 5 | 56 | 54 | 86 |
第一趟得到结果 51,45,5,56,54,86
第二趟排序
第一次:51和45比较,交换位置
45 | 51 | 5 | 56 | 54 | 86 |
第二次:51和5比较,交换位置
45 | 5 | 51 | 56 | 54 | 86 |
第三次:51和56比较,不交换位置
45 | 5 | 51 | 56 | 54 | 86 |
第四次:56和54比较,交换位置
45 | 5 | 51 | 54 | 56 | 86 |
第二趟得到的结果:
45 | 5 | 51 | 54 | 56 | 86 |
第三趟排序
第一次:45和5比较,交换位置
5 | 45 | 51 | 54 | 56 | 86 |
第二次:45和51比较,不换位置
5 | 45 | 51 | 54 | 56 | 86 |
第三次:51和54比较,不交换位置
5 | 45 | 51 | 54 | 56 | 86 |
第三趟得到的结果:
5 | 45 | 51 | 54 | 56 | 86 |
第四趟排序
第一次:5和45比较,不交换位置
5 | 45 | 51 | 54 | 56 | 86 |
第二次:45和51比较,不交换位置
5 | 45 | 51 | 54 | 56 | 86 |
第三趟得到的结果:
5 | 45 | 51 | 54 | 56 | 86 |
第五趟排序
第一次:5和45比较,不交换位置
5 | 45 | 51 | 54 | 56 | 86 |
第五趟得到结果
5 | 45 | 51 | 54 | 56 | 86 |
最终结果为
5 | 45 | 51 | 54 | 56 | 86 |
代码实现:
function Res(arr){
let temp;
for(let i=0;i<arr.length-1;i++){ //执行多少趟
for(let j=0;j<arr.length-1;j++){
if(arr[j]>arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1]
arr[j+1] =temp;
}
}
}
return arr
}
console.log(Res([5,4,2,6,7,8,2]))
这样就基本把冒泡写好了,时间复杂度是O(n*n),但是还可以优化一下
因为我们的代码的第二个for循环,长度每次都是 j<arr.length-1 如第一趟把 86 放在最后面了
51 | 45 | 5 | 56 | 54 | 86 |
按照 j<arr.length-1 后面依然会和86对比,但实际情况是,我们不需要和86对比
也就是说趟之后,对比的长度要减少一位
function Res(arr){
let temp;
for(let i=0;i<arr.length-1;i++){ //执行多少趟
for(let j=0;j<arr.length-1-i;j++){ // 改动了这里
if(arr[j]>arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1]
arr[j+1] =temp;
}
}
}
return arr
}
console.log(Res([5,4,2,6,7,8,2]))
这样得到的时间复杂度也是n*n, 但是减少了不必要的排序
但是还可以再优化一下,比如有时候会有这种情况,例如数组
1 | 2 | 3 | 5 | 4 |
按照冒泡排序,只需要一遍就可以排序完了,但是上面的代码,会一直排序到最后,不会判断当前的数组是否已经排序完毕,所以这时候我们可以这么做,我把思路写下来。
首先我们设置一个 标志
如果整一趟都不需要换位置的时候 是不是意味着排序完了?是的吧?
在某一趟全部不需要置换的时候,就排序完了
function Res(arr){
let temp;
let makesure = true; //这就是标志
var count = 0
for(let i=0;i<arr.length-1;i++){ // 执行多少趟
console.log("第"+ ++count+"趟开始")
makesure = true;
for(let j=0;j<arr.length-1-i;j++){ // 改动了这里
if(arr[j]>arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1]
arr[j+1] =temp;
makesure = false;
}
}
if(makesure == true){
break;
}
}
return arr
}
console.log(Res([1,2,3,5,4]))
就执行了2趟,因为第二趟不需要置换位置,所以就认为全部置换完毕
这时候最好的结果就是执行了1遍,复杂度就是O(n)
所以冒泡排序的时间复杂度是
最好情况 | 最坏情况 | 平均情况 |
O(n) | O(n*n) | O(n*n) |