让星星⭐月亮告诉你,Java冒泡排序及其时间复杂度计算

简介: 冒泡排序是一种简单的排序算法,通过多次遍历数组,每次比较相邻元素并交换位置,将较小的元素逐步移至数组前端。第一轮结束后,最小值会位于首位;第二轮则将次小值置于第二位,依此类推。经过 (n-1) 轮遍历后,数组完成排序。冒泡排序的时间复杂度为 O(n²),在最优情况下(已排序数组)时间复杂度为 O(n)。示例代码展示了如何实现冒泡排序。

⭐⭐⭐冒泡排序算法🌙🌙🌙:

  • 第一轮冒泡排序
    • 第一次拿数组的第1位和第2位进行比较,若第1位大于第2位,则将两者的值交换,
    • 再继续拿交换后的第1位与第3位进行比较,若第1位大于第3位,则将两者的值交换,
    • 然后再继续拿交换后的第1位与后续位进行比较,直到第1位与后续所有位置都比较完毕,最后会发现第一轮冒泡排序的最终结果是把最小值放到了第1位;
  • 第二轮冒泡排序:因为第一轮已经把最小值放到了第1位,则第二轮应该从第2位开始
    • 第一次拿数组的第2位和第3位进行比较,若第2位大于第3位,则将两者的值交换,
    • 再继续拿交换后的第2位与第4位进行比较,若第2位大于第4位,则将两者的值交换,
    • 然后再继续拿交换后的第2位与后续位进行比较,直到第2位与后续所有位置都比较完毕,最后会发现第二轮冒泡排序的最终结果是把次小值放到了第2位;
  • 后续轮次的排序思想跟前两轮类似,每次冒泡排序,都会把剩余位置里最小的那个值放到该次冒泡排序的起始位置,这样经过(数组长度-1)轮的冒泡后,就可以得到一个排好序的数组啦。
    冒泡排序时间复杂度
    • 假设数组的长度为n,从上述算法表述中可得,会经历(n-1)轮冒泡,而每一轮的冒泡里面其实又经历了(n-m)次的比值交换处理,m代表的是第几轮:
    • 正数第1轮,经历(n-1)次比值交换
    • 正数第2轮,经历(n-2)次比值交换
    • ...
    • 倒数第2轮,经历2次比值交换
    • 倒数第1轮,经历1次比值交换
    • 故,可得,总耗费步骤为:(n-1)+(n-2)+...2+1=[(1+(n-1))(n-1)]/2=(n(n-1))/2=(n²-n)/2=n²/2-n/2,根据时间复杂度计算原则,去掉常量,低阶项,再去掉高阶项的常量系数,得到时间复杂度为T(n)= =O(n²)。
    • 最优情况(O(n)):由于算法结构的限定,(n-1)轮的外层冒泡排序肯定是要进行的,而每一轮的冒泡排序里的比值交换则次数,在最优情况下,即数组已经排好序的情况下,里层的比值交换次数为0,即不需要交换。
    • 最坏情况(O(n²)):与要排序的顺序完全相反,即上述时间复杂度推导过程。
      • */
import java.util.Arrays;
public class BubbleSort {
   
    public static void main(String[] args) {
   
        int count = 0;
        int[] arr = {
   5,4,3,2,1};
        System.out.println("原始数组:" + Arrays.toString(arr));
        for(int i=0; i<arr.length-1; i++){
   
            System.out.println(i+1);
            for(int j=i+1;j<arr.length;j++){
   
                if(arr[i]>arr[j]){
   
                    int temp = arr[j];
                    arr[j]=arr[i];
                    arr[i]=temp;
                    System.out.println(Arrays.toString(arr) + (++count));
                }
            }
        }
    }    
}
目录
相关文章
|
2月前
|
Java
让星星⭐月亮告诉你,自定义定时器和Java自带原生定时器
定时器是一种可以设置多个具有不同执行时间和间隔的任务的工具。本文介绍了定时器的基本概念、如何自定义实现一个定时器,以及Java原生定时器的使用方法,包括定义定时任务接口、实现任务、定义任务处理线程和使用Java的`Timer`与`TimerTask`类来管理和执行定时任务。
58 3
|
1月前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
57 2
|
1月前
|
分布式计算 Java MaxCompute
ODPS MR节点跑graph连通分量计算代码报错java heap space如何解决
任务启动命令:jar -resources odps-graph-connect-family-2.0-SNAPSHOT.jar -classpath ./odps-graph-connect-family-2.0-SNAPSHOT.jar ConnectFamily 若是设置参数该如何设置
|
2月前
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
29 1
|
2月前
|
Java
让星星⭐月亮告诉你,Java synchronized(*.class) synchronized 方法 synchronized(this)分析
本文通过Java代码示例,介绍了`synchronized`关键字在类和实例方法上的使用。总结了三种情况:1) 类级别的锁,多个实例对象在同一时刻只能有一个获取锁;2) 实例方法级别的锁,多个实例对象可以同时执行;3) 同一实例对象的多个线程,同一时刻只能有一个线程执行同步方法。
22 1
|
2月前
|
Java
让星星⭐月亮告诉你,Java异常分类[Throwable(Error/Exception(RuntimeException/其他异常)) 检查时异常 非检查时异常]
本文深入解析了Java异常处理机制,重点介绍了`Throwable`类及其子类`Error`和`Exception`,并通过实例代码、流程图和表格详细解释了异常的分类、区别及处理方法,帮助读者掌握异常处理的关键技巧,提升程序的稳定性和健壮性。
61 1
|
1月前
|
Java API Apache
java集合的组内平均值怎么计算
通过本文的介绍,我们了解了在Java中计算集合的组内平均值的几种方法。每种方法都有其优缺点,具体选择哪种方法应根据实际需求和场景决定。无论是使用传统的循环方法,还是利用Java 8的Stream API,亦或是使用第三方库(如Apache Commons Collections和Guava),都可以有效地计算集合的组内平均值。希望本文对您理解和实现Java中的集合平均值计算有所帮助。
36 0
|
5天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
35 6
|
20天前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
18天前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####