JavaScript - js进阶 - 数组排序 - 冒泡算法

冒泡排序算法详解与优化实例

数组排序-冒泡算法

  • 算法algorithm,是一种解决问题的方法
  • 算法的目标:使用最少的内存,最短的时间,解决最多的问题
  • 冒泡算法:
    • 重复地走访过要排序的元素列,依次比较两个相邻的元素
      • 顺序正确:代表位置正确,不需要交换
      • 顺序错误:交换两个元素,让顺序正确
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>冒泡排序算法</title>
    </head>
    <body></body>
    <script>
        let arr = [3, 2, 5, 1, 4, 7, 5, 6, 2, 1, 9, 100, 0, -2];
        // 顺序混乱数组

        // 需求: 顺组元素从小到大排列: 升序排列

        // 1. 交换数组元素: 第一个和第二个
        // let temp = arr[0]
        // arr[0] = arr[1]
        // arr[1] = temp
        // console.log(arr)

        // 2. 遍历数组: 挨个交换
        // for (let i = 0; i < arr.length; i++) {
        //     // i = 0: 第一个与后一个(i+1)
        //     // i = 1: 第二个与后一个
        //     if (arr[i] > arr[i + 1]) {
        //         // 要交换位置
        //         let temp = arr[i]
        //         arr[i] = arr[i + 1]
        //         arr[i + 1] = temp
        //     }
        // }

        // console.log(arr)

        // 3. 一次循环过滤(交换): 只能搞定一个正确的位置: 给交换的循环再套一个循环
        for (let j = 0; j < arr.length; j++) {
            for (let i = 0; i < arr.length; i++) {
                // i = 0: 第一个与后一个(i+1)
                // i = 1: 第二个与后一个
                if (arr[i] > arr[i + 1]) {
                    // 要交换位置
                    let temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
        }

        console.log(arr);

        // 冒泡总结
        // 核心逻辑: 遍历 + 交换: 解决一个小目标 ; 循环嵌套: 不断解决小目标
    </script>
</html>

优化

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>冒泡排序算法 - 优化</title>
    </head>
    <body></body>
    <script>
        // let arr = [3, 2, 5, 1, 4, 7, 5, 6, 2, 1, 9, 100]
        let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

        /* let count = 0
        for (let j = 0; j < arr.length; j++) {
            for (let i = 0; i < arr.length; i++) {
                count++
                // i = 0: 第一个与后一个(i+1)
                // i = 1: 第二个与后一个
                if (arr[i] > arr[i + 1]) {
                    // 要交换位置
                    let temp = arr[i]
                    arr[i] = arr[i + 1]
                    arr[i + 1] = temp
                }
            }
            console.log(arr)
        }
        console.log(count) */

        // 优化: 算法没有最好,只有更好

        // 优化1: 数组进行元素交换的时候 , 因为要读取后一个进行交换: 前一个可以达到最后一个: 可以让下标只到倒数第二个即可
        /* let count = 0
        for (let j = 0; j < arr.length; j++) {
            // 优化1: 交换的循环,不要到最后一个: 倒数第二个即可
            for (let i = 0; i < arr.length - 1; i++) {
                count++
                // i = 0: 第一个与后一个(i+1)
                // i = 1: 第二个与后一个
                if (arr[i] > arr[i + 1]) {
                    // 要交换位置
                    let temp = arr[i]
                    arr[i] = arr[i + 1]
                    arr[i + 1] = temp
                }
            }
            console.log(arr)
        }
        console.log(count) */

        // 优化2: 每一次交换的循环都会确定一个最大的放到对应的位置(确定一个正确的位置), 第二次循环就可以避免去触碰那个已经正确位置的元素: 没循环一次, 就会出现一个对的位置
        /*  let count = 0
         for (let j = 0; j < arr.length; j++) {
             // 优化1: 交换的循环,不要到最后一个: 倒数第二个即可
             // 优化2: 外部循环执行1次, 内部循环可以减少一个交换判定
             for (let i = 0; i < arr.length - 1 - j; i++) {
                 count++
                 // i = 0: 第一个与后一个(i+1)
                 // i = 1: 第二个与后一个
                 if (arr[i] > arr[i + 1]) {
                     // 要交换位置
                     let temp = arr[i]
                     arr[i] = arr[i + 1]
                     arr[i + 1] = temp
                 }
             }
             console.log(arr)
         }
         console.log(count) */

        // 优化3: 如果元素根本就没有交换: 说明已经排好序了: 可以增加逻辑判定: 如果整个交换逻辑没有发生: 认为已经排好序: 可以提前结束了
        let count = 0;
        for (let j = 0; j < arr.length; j++) {
            // 优化1: 交换的循环,不要到最后一个: 倒数第二个即可
            // 优化2: 外部循环执行1次, 内部循环可以减少一个交换判定
            // 优化3: 定义一个变量: 假设没有进行交换
            let change = false;
            for (let i = 0; i < arr.length - 1 - j; i++) {
                count++;
                // i = 0: 第一个与后一个(i+1)
                // i = 1: 第二个与后一个
                if (arr[i] > arr[i + 1]) {
                    // 要交换位置
                    let temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;

                    // 说明交换
                    change = true;
                }
            }
            console.log(arr);

            // 判定
            if (!change) {
                break;
            }
        }
        console.log(count);
    </script>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Henry_ww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值