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!


相关文章
|
10天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
32 6
|
12天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。
|
12天前
|
人工智能 算法 大数据
Linux内核中的调度算法演变:从O(1)到CFS的优化之旅###
本文深入探讨了Linux操作系统内核中进程调度算法的发展历程,聚焦于O(1)调度器向完全公平调度器(CFS)的转变。不同于传统摘要对研究背景、方法、结果和结论的概述,本文创新性地采用“技术演进时间线”的形式,简明扼要地勾勒出这一转变背后的关键技术里程碑,旨在为读者提供一个清晰的历史脉络,引领其深入了解Linux调度机制的革新之路。 ###
|
20天前
|
Java 数据库连接 数据库
优化之路:Java连接池技术助力数据库性能飞跃
在Java应用开发中,数据库操作常成为性能瓶颈。频繁的数据库连接建立和断开增加了系统开销,导致性能下降。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接,显著减少连接开销,提升系统性能。文章详细介绍了连接池的优势、选择标准、使用方法及优化策略,帮助开发者实现数据库性能的飞跃。
25 4
|
18天前
|
存储 Java 开发者
成功优化!Java 基础 Docker 镜像从 674MB 缩减到 58MB 的经验分享
本文分享了如何通过 jlink 和 jdeps 工具将 Java 基础 Docker 镜像从 674MB 优化至 58MB 的经验。首先介绍了选择合适的基础镜像的重要性,然后详细讲解了使用 jlink 构建自定义 JRE 镜像的方法,并通过 jdeps 自动化模块依赖分析,最终实现了镜像的大幅缩减。此外,文章还提供了实用的 .dockerignore 文件技巧和选择安全、兼容的基础镜像的建议,帮助开发者提升镜像优化的效果。
|
22天前
|
存储 缓存 算法
优化轮询算法以提高资源分配的效率
【10月更文挑战第13天】通过以上这些优化措施,可以在一定程度上提高轮询算法的资源分配效率,使其更好地适应不同的应用场景和需求。但需要注意的是,优化策略的选择和实施需要根据具体情况进行详细的分析和评估,以确保优化效果的最大化。
|
22天前
|
存储 缓存 Java
Java应用瘦身记:Docker镜像从674MB优化至58MB的实践指南
【10月更文挑战第22天】 在容器化时代,Docker镜像的大小直接影响到应用的部署速度和运行效率。一个轻量级的Docker镜像可以减少存储成本、加快启动时间,并提高资源利用率。本文将分享如何将一个Java基础Docker镜像从674MB缩减到58MB的实践经验。
36 1
|
26天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
11天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
13天前
|
存储 算法 决策智能
基于免疫算法的TSP问题求解matlab仿真
旅行商问题(TSP)是一个经典的组合优化问题,目标是寻找经过每个城市恰好一次并返回起点的最短回路。本文介绍了一种基于免疫算法(IA)的解决方案,该算法模拟生物免疫系统的运作机制,通过克隆选择、变异和免疫记忆等步骤,有效解决了TSP问题。程序使用MATLAB 2022a版本运行,展示了良好的优化效果。

热门文章

最新文章