java基础算法系列(冒泡排序的简单优化讲解一)

简介: java基础算法系列(冒泡排序的简单优化讲解一)

   java的经典排序讲解以及简单优化

   java面试中一般都会遇到让你手写三大排序伪代码的场景。

   java排序分四类

1、插入排序
        直接插入排序
        希尔排序
2、交换排序
        冒泡排序
        快速排序
3、选择排序
        简单选择排序
        堆排序
        快速排序    
4、归并排序

面试中,我们面得最多的应该要数冒泡排序了,我们就先来讲讲冒泡排序。

正常情况下,我们进行伪代码的编写,或者需要在电脑上敲出来,冒泡排序是比较经典的排序:下面我们简单实现一下:

我将时间运行时间打印了出来,可能是由于数据量比较少的原因,时间ms显示不出来,我选择单位为ns,可以直观的看出来排序算法效率对比。


public static void main(String[] args) {
        int[] arr = { 1, 3, 4, 2, 6, 7, 8, 0, 5 };
        int i = 0;
        int tmp = 0;
        long startTime = System.nanoTime(); // 获取开始时间
        for (i = 0; i < arr.length - 1; i++) {
            // 确定排序趟数
            int j = 0;
            for (j = 0; j < arr.length - 1 - i; j++) {
                // 确定比较次数
                if (arr[j] > arr[j + 1]) {
                    // 交换
                    tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                }
            }
        }
        long endTime = System.nanoTime(); // 获取结束时间
        System.out.println("排序結果:" + Arrays.toString(arr));
        System.out.println("程序运行时间: " + (endTime - startTime) + "ns");
    }

控制台打印如下:

排序結果:[0, 1, 2, 3, 4, 5, 6, 7, 8]
程序运行时间:3800ns

上述代码是比较两个相邻的数,如果前面的数大于后面的数,则交换位置,重复执行,随着参与比较的元素越来越少,当最后一个元素比较完成时,则排序完成。

但是这样做有一个问题,如果我们的数据前面已经是有序的了,只是在后面才是无序的,比如int[] arr = {0, 1, 2, 3, 4, 6, 7, 8, 5 };

前面5位数都是有序的。这样,我们有一些排序就将是多余的,那么我们应该怎么优化呢,我们可以尝试着立下一个flag,用来标记,判断这一趟排序是否交换元素,如果有序的话我们就没必要进行下去。

优化代码如下:

public static void main(String[] args) {
        int[] arr = { 1, 3, 4, 2, 6, 7, 8, 0, 5 };
        int i = 0;
        int tmp = 0;
        long startTime=System.nanoTime();   //获取开始时间
        for (i = 0; i < arr.length - 1; i++){
            // 确定排序趟数
            int j = 0;
            Boolean flag = true;
            for (j = 0; j < arr.length - 1 - i; j++){
                // 确定比较次数
                if (arr[j] > arr[j + 1]){
                    // 交换
                    tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    flag = false;// 加入标记
                }
            }
            if (flag == true)
            {
                //未交换元素,结束当前循环,但是外面需要打印,所以这里不用return结束
                continue;
            }
        }
        long endTime=System.nanoTime(); //获取结束时间
        System.out.println("排序結果:" + Arrays.toString(arr));
        System.out.println("程序运行时间: "+(endTime-startTime)+"ns");
    }

控制台打印如下:

排序結果:[0, 1, 2, 3, 4, 5, 6, 7, 8]
程序运行时间:3500ns

但是这样我们又会发现一个问题,那就是上述代码对前面无序,而后面有序的数组排列,效率并不客观,那么我们可以标记一个位置,记录上次排序到哪,后面没有排序,后面的顺序则必然是有序的。

再次优化代码如下:

public static void main(String[] args) {
        int[] arr = { 1, 3, 4, 2, 6, 7, 8, 0, 5 };
        int i = 0;
        int tmp = 0;
        Boolean flag = true;
        int pos = 0;// 用来记录最后一次交换的位置
        int k = arr.length - 1;
        long startTime = System.nanoTime(); // 获取开始时间
        for (i = 0; i < arr.length - 1; i++) {
            pos = 0;
            int j = 0;
            flag = true;
            for (j = 0; j < k; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 交换
                    tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    flag = false;// 加入标记
                    pos = j;// 交换元素,记录最后一次交换的位置
                }
            }
            if (flag == true)// 如果没有交换过元素,则已经有序
            {
                continue;
            }
            k = pos;// 下一次比较到记录位置即可
        }
        long endTime = System.nanoTime(); // 获取结束时间
        System.out.println("排序結果:" + Arrays.toString(arr));
        System.out.println("程序运行时间: " + (endTime - startTime) + "ns");
    }

控制台打印如下:

排序結果:[0, 1, 2, 3, 4, 5, 6, 7, 8]
程序运行时间:3001ns

可能是由于数据顺序的问题,差距并不是特别大,冒泡排序适用于数组基本有序的情况,也就是数据本身不是太乱。并且元素不能太多,太多元素前后交换位置还是会有效率问题。

看完本系列文章,去面试offer又能多2K!


相关文章
|
3月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
442 35
|
3月前
|
存储 算法 搜索推荐
《数据之美》:Java数据结构与算法精要
本系列深入探讨数据结构与算法的核心原理及Java实现,涵盖线性与非线性结构、常用算法分类、复杂度分析及集合框架应用,助你提升程序效率,掌握编程底层逻辑。
|
3月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
163 8
|
3月前
|
机器学习/深度学习 算法 数据可视化
基于MVO多元宇宙优化的DBSCAN聚类算法matlab仿真
本程序基于MATLAB实现MVO优化的DBSCAN聚类算法,通过多元宇宙优化自动搜索最优参数Eps与MinPts,提升聚类精度。对比传统DBSCAN,MVO-DBSCAN有效克服参数依赖问题,适应复杂数据分布,增强鲁棒性,适用于非均匀密度数据集的高效聚类分析。
|
3月前
|
机器学习/深度学习 算法
采用蚁群算法对BP神经网络进行优化
使用蚁群算法来优化BP神经网络的权重和偏置,克服传统BP算法容易陷入局部极小值、收敛速度慢、对初始权重敏感等问题。
368 5
|
3月前
|
机器学习/深度学习 人工智能 算法
【基于TTNRBO优化DBN回归预测】基于瞬态三角牛顿-拉夫逊优化算法(TTNRBO)优化深度信念网络(DBN)数据回归预测研究(Matlab代码实现)
【基于TTNRBO优化DBN回归预测】基于瞬态三角牛顿-拉夫逊优化算法(TTNRBO)优化深度信念网络(DBN)数据回归预测研究(Matlab代码实现)
180 0
|
3月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
3月前
|
机器学习/深度学习 算法 物联网
基于遗传方法的动态多目标优化算法
基于遗传方法的动态多目标优化算法
|
3月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
370 0