js冒泡排序

3,914 阅读3分钟

1、冒泡排序的思路

一个有8位元素的数组,让它的第一位与后面每一位进行比较,前面一位小于后面的时候,位置不变,前面的大于后面的交换位置,就这样一共要比七趟(最后一趟不要比,就剩一位,就是最小的);

实现原理如下图:

image

2、按性能等级冒泡排序分3个等级

1、冒泡排序(初级):

let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
let tang = 0;
let ci = 0;
for (let i = 0; i < arr.length - 1; i++) {       // 外层for循环,循环的是比较的趟数,因为只要比较8趟 所以i判断的条件为length-1
    tang++;
    for (let j = 0; j < arr.length - 1; j++) {   // 内层for循环,循环的是比较的次数,每趟比较8次
        ci++;
        if (arr[j] > arr[j + 1]) {  // 判断比较的两个数,如果前面的大于后面的一位,交换位置
            let temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
}
console.log("趟数:" + tang);   // 8趟
console.log("次数:" + ci);     // 64次
console.log(arr);
}
  • 外层for循环,循环的是比较的趟数,因为只要比较8趟(数组长度为9) 所以i判断的条件为length-1
  • 内层for循环,循环的是比较的次数,每趟比较8次,其实这里次数多比较了,因为第一趟已经找到一个最大值了,第二趟就不需要比8次了 应该比7次,这里先不管,下面会进行优化;
  • 判断比较的两个数,如果前面的大于后面的一位,交换位置。

测试代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <span id="demo"></span><br/>
    <button id="stb">从小到大</button>
    <button id="bts">从大到小</button>
    <span id="show"></span>
    <script>
        let demo = document.getElementById("demo");
        let show = document.getElementById("show");
        let bts = document.getElementById("bts");
        let stb = document.getElementById("stb");

        let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
        demo.innerHTML = arr;

        bts.onclick = function() {
            bubbleSort(function(a, b) {
                return b - a;
            });
        }
        stb.onclick = function() {
            bubbleSort(function(a, b) {
                return a - b;
            });
        }

        function bubbleSort(fn) {
            let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
            let strArr = [];
            show.innerHTML = "";
            strArr.push("<br/>");
            let inner = 0;
            let outer = 0;
            for (let i = 0; i < arr.length - 1; i++) {
                strArr.push("第" + (i + 1) + "趟");
                for (let j = 0; j < arr.length - 1; j++) {
                    if (fn(arr[j], arr[j + 1]) > 0) {
                        let tmp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = tmp;
                    }
                    inner++;
                }
                strArr.push(arr.toString());
                strArr.push("共" + j + "次" + "<br/>");
                outer++;
            }
            strArr.push("外循环" + outer + "次");
            strArr.push("内循环" + inner + "次");
            show.innerHTML = strArr.join(" ");
        }
    </script>
</body>

</html>

image

每趟都比较8次?明显是多余了,下面进行优化

2、冒泡排序(中级):

let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
let tang = 0;
let ci = 0;
for (let i = 0; i < arr.length - 1; i++) {
    tang++;
    for (let j = 0; j < arr.length - 1 - i; j++) {  // 第二趟只比了7次 依次递减
        ci++;
        if (arr[j] > arr[j + 1]) {
            let temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
}
console.log("趟数:" + tang); // 8趟
console.log("次数:" + ci);   // 36次
console.log(arr);

i 是从下标0开始的,第一趟的时候i=0,比了8次,第二趟i=1,只需要比7次,第三趟i=2,只需要比6次...依次类推,所以 比的次数应该就是arr.length - 1 -i;

测试代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <span id="demo"></span><br/>
    <button id="stb">从小到大</button>
    <button id="bts">从大到小</button>
    <span id="show"></span>
    <script>
        let demo = document.getElementById("demo");
        let show = document.getElementById("show");
        let bts = document.getElementById("bts");
        let stb = document.getElementById("stb");

        let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];

        demo.innerHTML = arr;

        bts.onclick = function() {
            bubbleSort(function(a, b) {
                return b - a;
            });
        }
        stb.onclick = function() {
            bubbleSort(function(a, b) {
                return a - b;
            });
        }

        function bubbleSort(fn) {
            let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];

            let strArr = [];
            show.innerHTML = "";
            strArr.push("<br/>");
            let inner = 0;
            let outer = 0;
            for (let i = 0; i < arr.length - 1; i++) {
                strArr.push("第" + (i + 1) + "趟");
                for (let j = 0; j < arr.length - 1 - i; j++) {
                    if (fn(arr[j], arr[j + 1]) > 0) {
                        let tmp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = tmp;
                    }
                    inner++;
                }
                strArr.push(arr.toString());
                strArr.push("共" + j + "次" + "<br/>");
                outer++;
            }
            strArr.push("外循环" + outer + "次");
            strArr.push("内循环" + inner + "次");
            show.innerHTML = strArr.join(" ");
        }
    </script>
</body>

</html>

image

还有什么可以优化的吗? 假如8个数在第3趟的时候就排好了,还需要继续排吗?

3、冒泡排序(高级):

假设成立法(3步):

  • 假设成立
  • 想办法推翻假设
  • 如果推翻不了,说明假设成立
let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
let tang = 0;
let ci = 0;
for (let i = 0; i < arr.length - 1; i++) {
    let flag = true;   // 假设每一次进来都排好了
    tang++;
    for (let j = 0; j < arr.length - 1 - i; j++) {
        ci++;
        if (arr[j] > arr[j + 1]) {
            flag = false;        // 如果两位比较还满足前面的比后面的大的时候,说明假设不成立
            let temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
    if (flag == true) {    // 最后判断一下,如果假设推翻不了,就停止运行。
        break;
    }
}
console.log("趟数:" + tang);   // 4 趟
console.log("次数:" + ci);     // 26 次
console.log(arr);

当顺序已经排好后,就不用再去执行趟数了;

测试代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <span id="demo"></span><br/>
    <button id="stb">从小到大</button>
    <button id="bts">从大到小</button>
    <span id="show"></span>
    <script>
        let demo = document.getElementById("demo");
        let show = document.getElementById("show");
        let bts = document.getElementById("bts");
        let stb = document.getElementById("stb");

        let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];

        demo.innerHTML = arr;

        bts.onclick = function() {
            bubbleSort(function(a, b) {
                return b - a;
            });
        }
        stb.onclick = function() {
            bubbleSort(function(a, b) {
                return a - b;
            });
        }

        function bubbleSort(fn) {
            let arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];

            let strArr = [];
            show.innerHTML = "";
            strArr.push("<br/>");
            let inner = 0;
            let outer = 0;
            for (let i = 0; i < arr.length - 1; i++) {
                let sorted = true;
                strArr.push("第" + (i + 1) + "趟");
                for (let j = 0; j < arr.length - 1 - i; j++) {
                    if (fn(arr[j], arr[j + 1]) > 0) {
                        let tmp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = tmp;
                        sorted = false;
                    }
                    inner++;
                }
                strArr.push(arr.toString());
                strArr.push("共" + j + "次" + "<br/>");
                outer++;
                if (sorted) {
                    break;
                }
            }
            strArr.push("外循环" + outer + "次");
            strArr.push("内循环" + inner + "次");
            show.innerHTML = strArr.join(" ");
        }
    </script>
</body>

</html>

image

第三趟已经排好了,为什么还要排第四趟呢? 原因很简单,因为第三趟的时候js是不知道你已经排好的,只有第四趟的时候,js再进行换位比较的时候,发现位置都不需要换了,说明排好了。