首页 > 其他分享 >冒泡排序理解

冒泡排序理解

时间:2024-09-11 16:20:27浏览次数:11  
标签:arr 复杂度 元素 交换 冒泡排序 理解 排序

1.1 思路

冒泡排序是一种简单的排序方法。

  • 基本思路是通过两两比较相邻的元素并交换它们的位置,从而使整个序列按照顺序排列。
  • 该算法一趟排序后,最大值总是会移到数组的最后面,那么接下来就不用再考虑这个最大值。
  • 一直重复这样的操作,最终就可以得到排序完成的数组。

这种算法是稳定的,即相等元素的相对位置不会发生变化。

  • 而且在最坏情况下,时间复杂度为O(n^2),在最好情况下,时间复杂度为O(n)。

因此,冒泡排序适用于数据规模小的场景。

1.2 动图展示

1.3 冒泡排序流程

冒泡排序的流程如下:

  1. 从第一个元素开始,逐一比较相邻元素的大小。
  2. 如果前一个元素比后一个元素大,则交换位置。
  3. 在第一轮比较结束后,最大的元素被移动到了最后一个位置。
  4. 在下一轮比较中,不再考虑最后一个位置的元素,重复上述操作。
  5. 每轮比较结束后,需要排序的元素数量减一,直到没有需要排序的元素。
  6. 排序结束。
  7. 这个流程会一直循环,直到所有元素都有序排列为止。

1.4 冒泡排序代码

// 定义函数,用于实现冒泡排序算法
function bubbleSort(arr: number[]): number[] {
  // 外层循环,控制需要比较的轮数
  for (let i = 0; i < arr.length - 1; i++) {
    // 内层循环,控制每轮需要比较的次数
    for (let j = 0; j < arr.length - 1 - i; j++) {
      // 如果前一个元素比后一个元素大,则交换它们的位置
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  // 返回排序后的数组
  return arr;
}

// 测试代码
const arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];
console.log(bubbleSort(arr));
// 输出:[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

说明:

  1. 冒泡排序是一种暴力枚举算法,通过多次循环比较相邻的元素,把最大的元素逐渐冒泡到数组末端。
  2. 外层循环:控制排序的趟数,每一轮排序会把最大的元素放到最后,因此每次循环需要比较的元素个数也会逐渐减少。
  3. 内层循环:比较相邻元素,如果左边元素比右边元素大,则交换位置。
  4. 冒泡排序是一种时间复杂度较高的算法,一般不用于大数据量的排序,但它很容易理解,是一种初学者学习排序算法的好

1.5 冒泡排序的时间复杂度

在冒泡排序中,每次比较两个相邻的元素,并交换它们的位置,如果左边的元素比右边的元素大,则交换它们的位置。这样的比较和交换的过程可以用一个循环实现。

  • 在最好的情况下,数组已经是有序的,那么比较和交换的次数是最少的。
    • 在这种情况下,比较次数是n-1次,交换次数是0次,其中n是数组的长度。
  • 在最坏的情况下,数组是逆序的,那么比较和交换的次数是最多的。
    • 在这种情况下,比较次数是n-1次,交换次数是n(n-1)/2次,其中n是数组的长度。
  • 在平均情况下,比较和交换的次数取决于数组的排列方式。
    • 一般来说,平均情况下比较次数是n-1次,交换次数是n(n-1)/4次,其中n是数组的长度。

冒泡排序的时间复杂度分析:

  • 最好情况:当序列已经有序,每次比较和交换操作都不会进行,只需要进行n-1次比较,时间复杂度为O(n)。
  • 最坏情况:当序列完全逆序,需要进行n-1轮比较和n-1次交换操作,时间复杂度为O(n^2)。
  • 平均情况:需要进行的比较和交换操作的次数在所有情况中的平均值,时间复杂度也是O(n^2)。

由此可见,冒泡排序的时间复杂度主要取决于数据的初始顺序,最坏情况下时间复杂度是O(n^2),不适用于大规模数据的排序。

1.6 冒泡排序小结

  • 冒泡排序适用于数据规模较小的情况,因为它的时间复杂度为O(n^2),对于大数据量的排序会变得很慢。
  • 同时,它的实现简单,代码实现也容易理解,适用于学习排序算法的初学者。
  • 但是,在实际的应用中,冒泡排序并不常用,因为它的效率较低。
  • 此外,冒泡排序比较和交换的次数较多,占用更多的存储空间和时间,不适用于处理大数据量的情况。
  • 因此,在实际应用中,冒泡排序通常被更高效的排序算法代替,如快速排序、归并排序等

标签:arr,复杂度,元素,交换,冒泡排序,理解,排序
From: https://blog.csdn.net/2403_86761661/article/details/142062366

相关文章

  • 深入理解 Redis 的文件事件处理器
    概述Redis的文件事件处理器是基于Reactor模式实现的,内部采用IO多路复用程序来同时监听多个套接字,当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时,与操作相对应的文件事件就会产生,此时文件事件处理器就会调用套接字之前关联好的事......
  • 一文理解协程----还不明白请来砍我
    说在前头:本文话糙理不糙,用大白话说明协程的核心思想,协程,指的是单个线程里执行多个并发任务,一个协程对应一个任务,重点来了,!!!协程是用户空间的概念,也就是说不管你一个线程里有多少个协程,在操作系统看来,你就是一个单线程,只要你有一处代码阻塞了,那么os就会挂起整个线程,所以说这多......
  • 深入理解DocumentFragment -文档片段
    什么是文档片段?(MDN解释:)DocumentFragment,文档片段接口,一个没有父对象的最小文档对象。它被作为一个轻量版的Document使用,就像标准的document一样,存储由节点(nodes)组成的文档结构。作用是什么与document相比,最大的区别是DocumentFragment不是真实DOM树的一部分,它的变化不会触......
  • 深入理解 TON 智能合约中的 reply 方法
    在智能合约的开发过程中,消息传递和响应机制是非常关键的部分。在TON(TheOpenNetwork)的智能合约系统中,为了使合约能够与用户进行互动,一般使用send或reply等函数。它们用于向外发送消息、事件通知,或反馈操作状态等。而在这其中,reply()则是一个专门用来将信息返回给调用者的......
  • Vue 生命周期与 TypeScript:深入理解组件生命周期
    Vue生命周期与TypeScript:深入理解组件生命周期引言Vue.js作为一种流行的前端框架,其组件生命周期是开发过程中不可或缺的一部分。理解并正确利用Vue的生命周期,可以帮助开发者构建更加健壮和可维护的应用。而当TypeScript与Vue结合使用时,这种优势得到了进一步的增强。Typ......
  • 面向对象编程(OOP)之深入理解
    前言:想象一下,你正在搭建一座乐高城堡。你不需要从头开始制作每一个砖块,而是利用现成的砖块,按照说明书进行组装。面向对象编程(OOP)也是类似的理念,它将复杂的程序分解成一个个独立的“砖块”——对象,然后通过组合这些对象来构建整个程序。1.封装:保护数据,控制访问就像乐高城......
  • 数码管学习之路(静动态数码管源码及学习理解)
    1,了解数码管分类及结构    数码管是一种半导体发光器件,其基本单元是发光二极管。数码管按段数一般分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管(多一个小数点显示)。当然也还有一些其他类型的数码管如“N”形管、“米”字管以及工业科研领域用的1......
  • 『QEmu』理解QEMU构建系统
    QEmu采用了一套由Kconfig发展而来的Domain-SpecificLanguage(DSL领域特定语言),和meson相结合。其特点是对于模块编译的依赖关系较为严格(QEmu文档自己说的),在大量不同种类的主板之间也可以对同样的模块采用同样的共享代码。对于开发者来说,一方面添加新的设备较为容易;另一方......
  • Vue CLI:初学者指南与深入理解
    VueCLI:初学者指南与深入理解简介VueCLI是一个强大的工具,它帮助开发者快速搭建Vue.js项目。无论你是初学者还是有经验的开发者,VueCLI都能提供便利的功能来加快开发流程。本文将带你从安装VueCLI开始,逐步创建一个简单的Vue应用,并深入理解其背后的一些核心概念。......
  • Kotlin协程的取消机制:深入理解和优雅实现
    本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点Kotlin协程提供了一种高效的方式来处理并发和异步任务。在协程的生命周期管理中,取消协程是一项重要的操作。本文将深入探讨Kotlin协程的取消机制,介绍除了直接使用Job的cancel......