function bubbleSort(arr) {
// 外层循环控制比较的轮数
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]){
// 当前一项比后一项大,进行交换
[arr[j], arr[j+1]] = [arr[j+1], arr[j]]
}
}
}
return arr
}
冒泡排序的一点心得
- 发现一个规律,既然每次都是当前一项比后一项大的时候才交换,这就说明
如果当前项是未到最终位置的数据中最大的,那么这个元素势必会在一轮排序中
一直进行交换直到交换到最终的位置上。所以在冒泡排序中一轮排序势必会确定好
一个元素的最终位置,那么下一轮排序的次数就会减少一次 - 外层循环arr.length-1的来历:
内循环一次就可以确定一个元素的位置,但不是数据有多少个就得内循环多少次,
在第arr.length-1次循环结束的时候,因为交换的动作是相互的,在第arr.length-1次的排序中
,一轮就确定了两个元素的最终位置。所以外循环只用走arr.length-1次就完成了。 - 内循环arr.length-1-i的来历:
外层的i值,是控制冒泡排序的整个轮数,而只要有元素的最终位置被确定那么这个轮数自然会减小。
当i=0时:意味着当前是第一轮排序,也意味着还没有元素被排到最终位置上,所以这个0就是没有元素
在最终位置上,那么arr.length-1-i的这些个元素还需要在内循环被排序,也就是内循环还需要
arr.length-1-i次。
优化冒泡排序
外循环优化:
当某一轮(非最后一轮)内循环里没有发生交换动作时,就说明该组数据已经有序。
后序的外层循环可以不用再走了,这是对外层循环的优化。
内循环优化:
既然每一次内循环都可以确定一个元素的最终位置,其实这个元素不是任意元素
而是,未排序元素里的最大值的元素,所以该元素确定的最终位置以及其之后的元素
位置必然都是有序的。
那么下一轮内循环的时候j的值就应该取到已有序的元素之前,这样进一步来缩小内
循环的次数。
function bubbleSort1(arr) {
let lastChangeIndex = 0 //最后一次交换的位置
let flag = false // 标记是否交换
for(let i=0; i<arr.length-1; i++) {
let sortBorder = arr.length-1-i //交换边界的初始值
for(let j=0; j<sortBorder; j++) {
if(arr[j] > arr[j+1]) {
[arr[j], arr[j+1]] = [arr[j+1], arr[j]]
lastChangeIndex = j // 最后一次交换的位置
flag = true //如果进行交换就改变flag的值
}
}
sortBorder = lastChangeIndex // 把最后一次交换的位置赋值给交换边界
if(!flag) {
break
}
}
return arr
}