常规
let arr = [5, 8, 6, 3, 9, 2, 1, 7];
//外层循环,控制轮数,每一次找到一个最大值,把最大值置换到数组最后
let len = arr.length - 1 //需要减去1,因为后面会有j+1。
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i; j++) { //这里要减去一个i,因为进行到第i轮时,数组最后i个数已经排好序了。
if (arr[j] > arr[j + 1]) { //需要把大叔置换到数组后面
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; //es6解构方式转换数组位置,不需要定义额外变量。
}
}
}
console.log(arr); // [1, 2, 3, 5, 6, 7, 8, 9]
优化
这一版代码做了小小的改动,利用布尔变量flag作为标记。如果在本轮排序中,元素有交换,则说明数列无序;如果没有元素交换,说明数列已然有序,直接跳出大循环
冒泡排序总会执行(N-1)+(N-2)+(N-3)+..+2+1趟,但如果运行到当中某一趟时排序已经完成,或者输入的是一个有序数组,那么后边的比较就都是多余的,为了避免这种情况,我们增加一个flag,判断排序是否在中途就已经完成(也就是判断有无发生元素交换)
function bubbleSort (arr) {
let len = arr.length - 1
for (let i = 0; i < len; i++) {
let flag = true;
for (let j = 0; j < len - i; j++) {
if (arr[j] > arr[j + 1]) {
flag = false; //元素有交换,则说明数列无序;
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
if (flag) break;
}
return arr;
}
变种
对于冒泡排序来说,能不能传入第二个参数(参数为函数),来控制升序和降序?
function buddle_sort(arr,fn){
let len = arr.length - 1
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i; j++) {
if (fn(arr[j], arr[j + 1]) > 0) { //arr[j] - arr[j + 1]>0 大于0升序,小于0降序
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
}
let arr=[5, 8, 6, 3, 9, 2, 1, 7]
buddle_sort(arr, (a, b) => a - b)
console.log(arr)//[1, 2, 3, 5, 6, 7, 8, 9]
buddle_sort(arr, (a, b) => b - a)
console.log(arr)// [9, 8, 7, 6, 5, 3, 2, 1]
这样也行
function buddle_sort(arr,fn){
let len = arr.length - 1
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i; j++) {
if (fn(arr[j], arr[j + 1])) { //这样也行 ,把判断挪出去
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
}
let arr=[5, 8, 6, 3, 9, 2, 1, 7]
buddle_sort(arr, (a, b) => a - b>0) //这里直接判断是否大于0 不用将ab反过来计算
console.log(arr)//[1, 2, 3, 5, 6, 7, 8, 9]
buddle_sort(arr, (a, b) => a - b<0) //这里直接判断是否大于0 不用将ab反过来计算
console.log(arr)// [9, 8, 7, 6, 5, 3, 2, 1]