排序算法图解之Java冒泡排序及优化
作者:兴趣使然黄小黄 发布时间:2022-07-16 01:28:38
1.冒泡排序简介
冒泡排序(Bubble Sorting)即:通过对待排序的序列从前往后,依次比较相邻元素的值,若发现逆序则交换位置,使较大的元素逐渐移动到后部,就像水底的气泡一样逐渐从水面冒出来,这就是冒泡名称的由来
2.图解算法
以将序列{3, 9, -1, 10, -20}从小到大排序为例!
基本思想就是,在每一趟排序实现将最大的数移到序列的最后端!这主要通过比较相邻两个元素实现,当相邻的两个元素逆序的时候,我们就交换它们。
第1趟排序:
第1趟排序共比较了4次,将最大的数10冒泡到了序列的尾部。
第2趟排序:
由于第一趟排序已经将最大是数10给冒泡到了最末端,因此在本次排序中,不需要再比较最后一个元素,故共比较了3次,将子序列(前四个元素)中最大的数9(整个序列中倒数第二大的数)冒泡到了子序列的尾端(原序列的倒数第二个位置)。
第3趟排序:
在第三趟排序时,同理,倒数两个元素位置已经确定,即第一、第二大的数已经排好位置,只需要再将倒数第三大的数确认即可。故比较2次,实现倒数第三大的数3的位置确定。
第4趟排序:
在第四趟排序时,只有第一、第二个元素的位置还不确定,只需要比较一次,若逆序,则交换即可。到此,排序算法完成,原序列已经排序成为一个递增的序列!
小结
一共进行了数组大小-1次趟排序,即外层循环arr.length-1次;每趟排序进行了逐趟减小次数的比较,即内层循环arr.length-i-1次,i从0依次增加。
3.冒泡排序代码实现
参考代码如下,为了便于观察结果,在循环中添加了相应的输出语句:
import java.util.Arrays;
/**
* @author 兴趣使然黄小黄
* @version 1.0
* 冒泡排序
*/
public class BubbleSort {
public static void main(String[] args) {
int[] array = {3, 9, -1, 10, -20};
//排序前
System.out.println("排序前:" + Arrays.toString(array));
//冒泡排序
for (int i = 0; i < array.length - 1; i++) {
System.out.println("第" + (i+1) + "趟排序开始!");
for (int j = 0; j < array.length - i - 1; j++) {
//如果前面的数比后面的数大,则交换
if(array[j] > array[j+1]){
//交换
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
System.out.println("------第" + (j+1) + "趟排序: " + Arrays.toString(array));
}
System.out.println("第" + (i+1) + "趟排序完成: " + Arrays.toString(array));
System.out.println("================================================");
}
//输出排序后的结果
System.out.println("排序后:" + Arrays.toString(array));
}
}
实现结果:
4.冒泡排序算法的优化
举个例子,将待排序的序列改为:{5,1,2,3,4},用以上算法来处理,观察一下结果:
可以发现,当第一趟排序结束的时候,序列已经排序完成: 即将5冒泡到了最后,序列实现了从小到大排序。但是原冒泡排序算法,还是义无反顾的进行了数组大小-1趟排序(我可真是大冤种!)
因此,我们需要尝试对算法进行优化!
发现:在冒泡排序的过程中,各个元素都在不断的接近自己的位置,如果下一趟比较中没有进行过任何交换,则说明序列已经有序, 则排序算法已经可以返回结果。因此,考虑在排序算法过程中添加一个标志flag判断元素是否进行过交换,以减少不必要的冤种行为!
优化代码如下:
import java.util.Arrays;
/**
* @author 兴趣使然黄小黄
* @version 1.0
* 冒泡排序优化
*/
public class BubbleSort {
public static void main(String[] args) {
int[] array = {5, 1, 2, 3, 4};
//排序前
System.out.println("排序前:" + Arrays.toString(array));
boolean flag = false; //用于标记是否进行了交换,true则说明进行了交换,false表示无
//冒泡排序
for (int i = 0; i < array.length - 1; i++) {
System.out.println("第" + (i+1) + "趟排序开始!");
for (int j = 0; j < array.length - i - 1; j++) {
//如果前面的数比后面的数大,则交换
if(array[j] > array[j+1]){
//交换
flag = true; //标记进行了交换
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
System.out.println("------第" + (j+1) + "趟排序: " + Arrays.toString(array));
}
System.out.println("第" + (i+1) + "趟排序完成: " + Arrays.toString(array));
System.out.println("================================================");
if (!flag){
//如果没有进行交换则直接退出,说明排序已经完成
break;
}else {
//回退
flag = false;
}
}
//输出排序后的结果
System.out.println("排序后:" + Arrays.toString(array));
}
}
四趟排序,优化成了只需要两趟排序!又是一个不可多得的小技巧!在算法程序题中,flag的设置是一种常用的编程思想,常常用于回溯算法中,小伙伴们要学会举一反三~
来源:https://blog.csdn.net/m0_60353039/article/details/127670013


猜你喜欢
- Synchronized关键字Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码
- 建库建表DROP DATABASE IF EXISTS mp;CREATE DATABASE mp DEFAULT CHARACTER SE
- 每年实验课,总有同学问我,如何生成DLL、如何导出类,如何不花很多时间精力,就设计出一个给别人用的爽的功能库呢?结合这些年的实践,我们今天就
- 如下所示:class B {public B() { super(); System.out.println(&qu
- 前段时间写了一篇基于mybatis实现的多数据源博客。感觉不是很好,这次打算加入git,来搭建一个基于Mybatis-Plus的多数据源项目
- 发一个库存程序,好像是几个礼拜之前写的吧,是一个用安卓实现的简易的计算器,写这个小程序之前,看了很多人写的计算器,觉得使用一个 EditTe
- 引入所谓泛型,就是创建一个函数,对所有数据类型都生效。最常见的例子就是运算符,毕竟1+1=2,1.0+1.0=2.0,足以看出+是对多种数据
- Objects工具类jdk 1.7引进的工具类,都是静态调用的方法,jdk 1.8新增了部分方法重点方法equals用于字符串和包装对象的比
- springboot URL带有斜杠的转义字符百分之2F导致的400错误今天项目上出现一个问题,是前端的GET请求url中带有路径参数,这个
- 1、线程数使用开发规约阿里巴巴开发手册中关于线程和线程池的使用有如下三条强制规约【强制】创建线程或线程池时请指定有意义的线程名称,方便出错时
- 首先我们要知道,微信的聊天记录一般是不提供给我们获取的,所以一般情况下我们手机没root的话就拿不到了。就算是root后的手机,想要获取微信
- 对于开发游戏项目的同胞来说,Timer 这个东西肯定不会陌生,今天对以前自己经常使用的定时进行了一番小小的总结!没有写具体实现的原理,只是列
- 前言从来没接触过flutter,我将在这里记录下我的flutter学习踩坑历程。安装就从安装开始叭,官网链接在此。先遵照官网教程来叭。系统要
- 本文实例讲述了C#移除所有事件绑定的方法。分享给大家供大家参考。具体分析如下:private delegate int DEL_TEST_E
- 前言假设项目打包后,项目结构为:此时如果需要再windows环境中进行项目的启动或关闭,需要频繁的手敲命令,很不方便。此时可以编写.bat脚
- 本文实例讲述了C#使用iTextSharp封装的PDF文件操作类。分享给大家供大家参考。具体分析如下:这个C#代码主要讲iTextSharp
- <results>标签在Struts2的MVC框架的视图中所扮演的角色。动作是负责执行业务逻辑。执行业务逻辑后,接下来的步骤是使
- 什么是XML?XML:可扩展标记语言。XML的作用:纯文本,兼容性强。和HTML的区别:xml: 主要用来处理、存储数据。无规定标签,可扩展
- 一、File类1、简介java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关 File 能新建、删除、重命名文件和目录,但
- 用java swing写的一个简单的五子棋游戏。下面是Main.java。package com.crossing.main;import