冒泡排序

冒泡排序的核心思路,就是每一轮都把最大的数"冒"到数组顶部.

1 算法过程

(从小到大排序)
1. 每一轮排序,都从第一个数开始,比较相邻的数;
2. 如果第一个数比第二个数大,则交换两个数的位置;
3. 如果第一个数不大于第二个数,则不交换位置,开始比较第二个数和第三个数;
4. 以此类推,直到比完最后两个数,选出数列最大值置于末尾;
5. 待排数列更新为原数列减去末尾值,开始下一轮排序,重复上面的步骤;

2 排序演示

对下面的数列进行冒泡排序:

3, 4, 1, 5, 2

第一轮排序开始,从第一个数3开始,比较相邻的数4

3, 4, 1, 5, 2
↑  ↑

3不大于4,不交换位置,开始比较第二个数4和第三个数1

3, 4, 1, 5, 2↑  ↑

4大于1,交换位置,开始比较第三个数4和第四个数5

3, 1, 4, 5, 2↑  ↑

4不大于5,不交换位置,开始比较第四个数5和最后一个数2

3, 1, 4, 5, 2↑  ↑

5大于2,交换位置,此时5已到达数列末尾,第一轮排序结束,排序结果为:

3, 1, 4, 2, 5

第二轮排序开始,待排数列为

3, 1, 4, 2

(5已经确认为上一轮排序数列的最大值,不参与第二轮排序)

从第一个数3开始,比较相邻的数1

3, 1, 4, 2
↑  ↑

3大于1,交换位置,比较第二个数3和第三个数4

1, 3, 4, 2↑  ↑

3不大于4,不交换位置,比较第三个数4和最后一个数2

1, 3, 4, 2↑  ↑

4大于2,交换位置,此时4已到达数列末尾,第二轮排序结束,排序结果为

1, 3, 2, 4

第三轮排序开始,待排数列为

1, 3, 2

从第一个数1开始,比较相邻的数3

1, 3, 2
↑  ↑

1不大于3,不交换位置,比较第二个数3和最后一个数2

3大于2,交换位置,此时3已到达数列末尾,第三轮排序结束,排序结果为

1, 2, 3

第四轮排序开始,待排数列为

1,2

从第一个数1开始,比较最后一个数2

1, 2
↑  ↑

1不大于2,不交换位置,此时2已是数列末尾,第四轮排序结束,排序结果为

1, 2

第五轮排序,待排数列只剩一个数1,排序结束,得到有序数组

1, 2, 3, 4, 5

3 基本实现

const arr = [3, 2, 5, 1, 4, 6, 9, 10, 8, 7];// 交换方法
function swap(arr, i, j) {let temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}// 冒泡排序
function bubbleSort() {// 缓存数组长度const len = arr.length;// 外层循环:需要多少轮排序for (let i = 0; i < len - 1; i++) {// 内层循环:一轮排序下,遍历待排数列进行比较和交换for (let j = 0; j < len - 1 - i; j++) {// 前面的数大于后面的数,则交换if (arr[j] > arr[j+1]) {// [arr[j], arr[j+1]] = [arr[j+1], arr[j]];swap(arr, j, j+1)}}}return arr;
}

4 优化

实际上,在前面的基本实现中,即使是在最好的情况下(原数列本身就是有序数列),如[1,2,3,4,5],他也需要比较n(n-1)/2次,也就是说,在最好的情况下对应的时间复杂度为O(n^2).

但我们知道,实际上在冒泡排序中,最好的情况下,我们只需要比较(n-1)次,交换0次就可以了.也就是说,在最好的情况下对应的时间复杂度应该是O(n).

为此需要对代码进行改进,那怎么改进呢?

也许你已经发现,在前面排序演示中,第三轮排序后,我们已经得到了有序数列,从第四轮排序开始,是不会有交换记录的.

因此,我们可以在一轮排序中添加一个检测变量flag,初始化为false,只要这轮排序有交换记录,就将其置为true.

一轮排序下来,如果flag仍然为false,说明数列已经有序,直接return,不再进行后面的循环.

代码如下:

// 冒泡排序
function bubbleSort() {// 缓存数组长度const len = arr.length;// 外层循环:需要多少轮排序for (let i = 0; i < len - 1; i++) {let flag = false;// 内层循环:一轮排序下,遍历待排数列进行比较和交换for (let j = 0; j < len - 1 - i; j++) {// 前面的数大于后面的数,则交换if (arr[j] > arr[j+1]) {// [arr[j], arr[j+1]] = [arr[j+1], arr[j]];swap(arr, j, j+1);flag = true;}}// 如果一轮排序没有交换记录,直接返回有序数列if (!flag) return arr;}return arr;
}

5 时间复杂度

  • 最好情况下,原数列有序,只需比较(n-1)次,交换0次,时间复杂度为O(n);
  • 最坏情况下,原数列逆序,需要比较和交换n(n-1)/2次,时间复杂度为O(n^2);
  • 平均时间复杂度为O(n^2).

6 稳定性

冒泡排序是通过不断的交换位置,将大的元素往后调(或把小的元素往前调).比较是发生在相邻两个元素之间,如果两个元素相等,不会进行交换.因此,冒泡排序是稳定的.

JavaScript实现排序算法(1)——冒泡排序相关推荐

  1. JavaScript实现排序算法

    排序算法主要用在元素的数组排序,常见的排序算法有冒泡排序.选择排序.插入排序.希尔排序.快速排序.归并排序等.这些排序算法都可以用JavaScript实现.下面的排序算法都假设是从小到大进行排序,从大 ...

  2. 十大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序

    冒泡排序.选择排序.插入排序.希尔排序.归并排序.快速排序.堆排序.计数排序.桶排序.基数排序的动图与源代码. 目录 关于时间复杂度 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 ...

  3. JavaScript的排序算法——快速排序

    排序算法(Sorting algorithm)是计算机科学最古老.最基本的课题之一.要想成为合格的程序员,就必须理解和掌握各种排序算法. 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排 ...

  4. Java排序算法:冒泡排序

    Java排序算法:冒泡排序 //创建数组并赋值int[] data = new int[] {11,10,55,78,100,111,45,56,79,90,345,1000};for(int i=0 ...

  5. 排序算法:冒泡排序、插入排序、选择排序、希尔排序

    相关博客: 排序算法:冒泡排序.插入排序.选择排序.希尔排序 排序算法:归并排序.快速排序 排序算法:桶排序.计数排序.基数排序 排序算法:堆排序 十大排序算法小结 一.冒泡排序: 1.算法原理: 冒 ...

  6. golang 排序_常用排序算法之冒泡排序

    周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...

  7. 数据结构与算法:十大排序算法之冒泡排序

    数据结构与算法:十大排序算法之冒泡排序 package array;import java.util.Arrays;//冒泡排序 //1.比较数组中两个相邻的元素,如果第一个数比第二个数大,我们就交换 ...

  8. 【排序算法】冒泡排序、简单选择排序、直接插入排序比较和分析

    [排序算法]冒泡排序.简单选择排序.直接插入排序比较和分析 写在前面: 本文简单介绍了冒泡排序.简单选择排序.直接插入排序,并对这三种排序进行比较,入参都是80000个随机数,比较算法耗时.进一步,我 ...

  9. 排序算法(1)冒泡排序

    排序算法(1)冒泡排序 原理: 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个. 2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 3. ...

最新文章

  1. OSPF完全配置2--NSSA
  2. c语言uint赋值给int,如何在C#中将uint转换为int?
  3. vba单元格批量赋值_Excel●VBA●如何把批注中的信息批量提取到单元格?
  4. Java线程中wait、await、sleep、yield、join用法总结
  5. linux下w和who使用说明
  6. db platform mysql_数据库移植: 从Oracle移植到MySQL 注意databasePlatform | 学步园
  7. iBatis.Net系列(五)-providers.config-
  8. axure element ui素材_Element - 饿了么团队出品的神级桌面 UI 组件库
  9. PHPWAMP强行脱离依赖,在系统缺失必备组件或DLL受损的情况下依然能正常运行
  10. MongoDB实验——数据库基本操作(头歌)
  11. spring三级缓存
  12. anki android 导入路径,3.1 导入卡片
  13. MATLAB求分段函数最大值,如何用MATLAB求分段函数的最小值和最大值?
  14. 上学的时候写的文本分割器
  15. Matlab 实时录音(声卡)及频谱显示
  16. UD三分区补充教程1——激活不同分区对于UD三分区bios启动和uefi启动兼容性影响的讨论
  17. Word文档中实现:点击图片双击放大
  18. Python线程和进程的了解,多线程多进程
  19. 周鸿祎:“作恶”的创新?
  20. Redis管理工具CacheCloud的部署与使用

热门文章

  1. nginx: [alert] could not open error log file: open() /usr/local/var/log/nginx/error.log
  2. 8.牛批了 Android 2022高级 资深面试题 一线大厂和二线大厂面试真题精选 (腾讯 附答案)第八套 35k+
  3. Maven工程下,解决配置文件相关的File doesn't exits,以及xxxMapper.xml doesn't exits
  4. linux shell命令对时间的处理(精确到秒、毫秒、纳秒)——筑梦之路
  5. ubuntu16.04下scp命令出现Permission denied, please try again(publickey,password)提示的解决
  6. Mastering Opencv学习笔记(1)——图片卡通化
  7. 怎么用c语言定义棋盘大小,求数据结构C语言大神们解释下马踏棋盘程序
  8. 超声波换能器发生器电源
  9. 黄静致华硕计算机总公司董事长的一封信
  10. 90后和他的“全球充电网络”梦