数据结构与算法之排序: 冒泡排序 (Typescript版)

排序

  • 排序:把某个乱序的数组变成升序或降序的数组 (这里用数组来做举例)

冒泡排序

  • 该排序属于 贪心 策略
  • 关注的是局部,是一种苟且的东西

算法实现

1 )version 1 初始版本

js 复制代码
Array.prototype.bubbleSort = function() {
    let len = this.length;
    for(let i =0; i<len; i++) {
        for(let j=0;j<len-1-i;j++) {
            if(this[j] > this[j+1]) {
                let tmp = this[j];
                this[j] = this[j+1];
                this[j+1] = tmp;
            }
        }
    }
}

let arr = [5,4,3,2,1]
arr.bubbleSort()
console.log(arr); // [1, 2, 3, 4, 5]

2 ) version 2 ES6 做两数交换 优化版

js 复制代码
Array.prototype.bubbleSort = function() {
    let len = this.length;
    for(let i =0; i<len; i++) {
        for(let j=0;j<len-1-i;j++) {
            if(this[j] > this[j+1]) {
               [this[j], this[j+1]] = [this[j+1], this[j]] // ES6 交换
            }
        }
    }
}

let arr = [5,4,3,2,1]
arr.bubbleSort()
console.log(arr); // [1, 2, 3, 4, 5]

3 ) version 3 冒泡排序,提前终止版

js 复制代码
Array.prototype.bubbleSort = function() {
    let len = this.length;
    let sorted = false; // 哨兵变量
    while(!sorted) {
        sorted = true; // 提前终止标识
        for(let i=0; i<len-1; i++) {
            if(this[i] > this[i+1]) {
                [this[i], this[i+1]] = [this[i+1], this[i]]
                sorted = false;
            }
        }
        // 如果经过上面一轮 sorted仍为true,没有变为false, 说明已经整体已经有序,可以提前终止了
        len --;
    }
}

let arr = [5,4,3,2,1]
arr.bubbleSort()
console.log(arr); // [1, 2, 3, 4, 5]

4 )version 4 冒泡排序,跳跃版

js 复制代码
Array.prototype.bubbleSort = function() {
    let len = this.length;
    let k = len - 1; // 跳跃标识
    let last = 0; // 内层循环标识
    let i = 0;

    // 第一层循环表示经过n-1趟扫描即可,每比较一趟,问题规模缩小1级,第一层循环次数必须不变 n-1 次
    while(i<len-1) {
        // 第二层循环表示每一趟进行两两逐个比较,找到最大的元素
        for(let j=0; j<k; ++j) {
            // 当前元素和后一个元素进行比较,若逆序
            if(this[j]>this[j+1]) {
                // 则交换
                [this[j], this[j+1]] = [this[j+1], this[j]];
                // 更新交换的位置
                last = j;
            }
        }
        // 在一层循环之后跳跃到最后交换的那个地方,这样的话,在k的位置,后面如果是有序,就可以直接跳过了
        k = last;
        ++i;
    }
}

let arr = [5,4,3,2,1]
arr.bubbleSort()
console.log(arr); // [1, 2, 3, 4, 5]

5 )version 5 冒泡排序,提前终止+跳跃版

js 复制代码
Array.prototype.bubbleSort = function() {
    let len = this.length;
    let k = len - 1; // 跳跃标识
    let last = 0; // 内层循环标识
    let i = 0; // 最外层循环标识
    let sorted = false; // 哨兵变量

    // 第一层循环表示经过n-1趟扫描即可,每比较一趟,问题规模缩小1级,第一层循环次数必须不变 n-1 次
    while(i<len-1 && !sorted) {
        sorted = true;
        // 第二层循环表示每一趟进行两两逐个比较,找到最大的元素
        for(let j=0; j<k; ++j) {
            // 当前元素和后一个元素进行比较,若逆序
            if(this[j]>this[j+1]) {
                // 则交换
                [this[j], this[j+1]] = [this[j+1], this[j]];
                // 更新交换的位置
                last = j;
                sorted = false;
            }
        }
        // 在一层循环之后跳跃到最后交换的那个地方,这样的话,在k的位置,后面如果是有序,就可以直接跳过了
        k = last;
        ++i;
    }
}

let arr = [5,4,3,2,1]
arr.bubbleSort()
console.log(arr); // [1, 2, 3, 4, 5]
  • 冒泡排序最简单,性能不好,工作中用不到
  • 思路
    • 比较所有相邻元素,如果第一个比第二个大,则交换他们
    • 一轮下来,可以保证最后一个数是最大的
    • 执行n-1轮就可以完成排序了
    • 我们可以看到每一轮循环是不一样的,执行区间越来越短
    • 冒泡排序是一种贪心策略
  • 动画示例:visualgo.net/zh/sorting
  • 时间复杂度:O( n 2 n^2 n2)
    • 两个嵌套循环
  • 总结
    • 该算法通过两两比较盯住当前最大的元素,逐渐将其移动到最后,继而一次有序,逐次比较达到整个序列完全有序
    • 不变性:经k趟扫描交换后,最大的k个元素必然就位
    • 单调性:经k趟扫描交换后,问题规模缩减至n-k
    • 正确性:经至多n趟扫描后,算法必然终止,且能给出正确解答
    • 它的核心思想是自左至右,逐一检查各对相邻元素,若有逆序,则交换
    • 这个算法其实只需要经过n-1趟比较就足够了, 有改进的空间
    • 如果某一趟比较后整体已经有序了,就没有必要继续比较到n-1趟了,即提前终止版
    • 也许一个算法的思想在一开始是基于很low的策略,比如greedy
    • 当基于这个greedy的算法不断做优化, 也能表现的非常好
    • 一共有4个版本的写法(上面 1,2是一种,所以是4种)
相关推荐
程序员莫小特13 小时前
老题新解|大整数加法
数据结构·c++·算法
过往入尘土14 小时前
服务端与客户端的简单链接
人工智能·python·算法·pycharm·大模型
zycoder.14 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
蒙奇D索大14 小时前
【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
数据结构·笔记·学习·考研·算法·改行学it
智驱力人工智能15 小时前
工厂抽烟检测系统 智能化安全管控新方案 加油站吸烟检测技术 吸烟行为智能监测
人工智能·算法·安全·边缘计算·抽烟检测算法·工厂抽烟检测系统·吸烟监测
程序员爱钓鱼15 小时前
Go语言实战案例——进阶与部署篇:编写Makefile自动构建Go项目
后端·算法·go
_Power_Y16 小时前
Java面试常用算法api速刷
java·算法·面试
艾醒(AiXing-w)16 小时前
大模型面试题剖析:模型微调中冷启动与热启动的概念、阶段与实例解析
人工智能·深度学习·算法·语言模型·自然语言处理
天选之女wow16 小时前
【代码随想录算法训练营——Day32】动态规划——509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯
算法·leetcode·动态规划
红衣小蛇妖16 小时前
LeetCode-704-二分查找
java·算法·leetcode·职场和发展