冒泡排序是非常好理解的,以从小到大排序为例,每一轮排序就找出未排序序列中最大值放在最后。

设数组的长度为N:
(1)比较前后相邻的二个数据,如果前面数据大于后面的数据,就将这二个数据交换。

(2)这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。

(3)N=N-1,如果N不为0就重复前面二步,否则排序完成。

以上就是冒泡排序的基本思想,按照这个定义很快就能写出代码:

  1. /**
  2. * 冒泡排序的第一种实现, 没有任何优化
  3. * @param a
  4. * @param n
  5. */
  6. public static void bubbleSort1(int [] a, int n){
  7. int i, j;
  8. for(i=0; i<n; i++){//表示n次排序过程。
  9. for(j=1; j<n-i; j++){
  10. if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
  11. //交换a[j-1]和a[j]
  12. int temp;
  13. temp = a[j-1];
  14. a[j-1] = a[j];
  15. a[j]=temp;
  16. }
  17. }
  18. }
  19. }// end

给出一个测试代码:

  1. public static void main(String[] args) {
  2. int[] arr = {1,1,2,0,9,3,12,7,8,3,4,65,22};
  3. BubbleSort.bubbleSort1(arr, arr.length);
  4. for(int i:arr){
  5. System.out.print(i+",");
  6. }
  7. }

运行结果:

  1. 0,1,1,2,3,3,4,7,8,9,12,22,65,

下面开始考虑优化,如果对于一个本身有序的序列,或则序列后面一大部分都是有序的序列,上面的算法就会浪费很多的时间开销,这里设置一个标志flag,如果这一趟发生了交换,则为true,否则为false。明显如果有一趟没有发生交换,说明排序已经完成。

  1. /**
  2. * 设置一个标志,如果这一趟发生了交换,则为true,否则为false。明显如果有一趟没有发生交换,说明排序已经完成。
  3. * @param a
  4. * @param n
  5. */
  6. public static void bubbleSort2(int [] a, int n){
  7. int j, k = n;
  8. boolean flag = true;//发生了交换就为true, 没发生就为false,第一次判断时必须标志位true。
  9. while (flag){
  10. flag=false;//每次开始排序前,都设置flag为未排序过
  11. for(j=1; j<k; j++){
  12. if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
  13. //交换a[j-1]和a[j]
  14. int temp;
  15. temp = a[j-1];
  16. a[j-1] = a[j];
  17. a[j]=temp;
  18. //表示交换过数据;
  19. flag = true;
  20. }
  21. }
  22. k--;//减小一次排序的尾边界
  23. }//end while
  24. }//end

运行测试main函数结果:

  1. 0,1,1,2,3,3,4,7,8,9,12,22,65,

再进一步做优化。比如,现在有一个包含1000个数的数组,仅前面100个无序,后面900个都已排好序且都大于前面100个数字,那么在第一趟遍历后,最后发生交换的位置必定小于100,且这个位置之后的数据必定已经有序了,也就是这个位置以后的数据不需要再排序了,于是记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。如果是对于上面的冒泡排序算法2来说,虽然也只排序100次,但是前面的100次排序每次都要对后面的900个数据进行比较,而对于现在的排序算法3,只需要有一次比较后面的900个数据,之后就会设置尾边界,保证后面的900个数据不再被排序。

  1. public static void bubbleSort3(int [] a, int n){
  2. int j , k;
  3. int flag = n ;//flag来记录最后交换的位置,也就是排序的尾边界
  4. while (flag > 0){//排序未结束标志
  5. k = flag; //k 来记录遍历的尾边界
  6. flag = 0;
  7. for(j=1; j<k; j++){
  8. if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
  9. //交换a[j-1]和a[j]
  10. int temp;
  11. temp = a[j-1];
  12. a[j-1] = a[j];
  13. a[j]=temp;
  14. //表示交换过数据;
  15. flag = j;//记录最新的尾边界.
  16. }
  17. }
  18. }
  19. }

这种方法是我看到的最优化的冒泡排序了。
运行测试例子结果:

  1. 0,1,1,2,3,3,4,7,8,9,12,22,65,
  • 1

可知运行结果正确。

冒泡排序的三种实现(Java)的更多相关文章

  1. c#之冒泡排序的三种实现和性能分析

    冒泡排序算法是我们经常见到的尤其是子一些笔试题中. 下面和大家讨论c#中的冒泡排序,笔者提供了三种解决方案,并且会分析各自的性能优劣. 第一种估计大家都掌握的,使用数据交换来实现,这种就不多说了,园子 ...

  2. 文件上传的三种模式-Java

    文件上传的三种方式-Java 前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对 Http 协议较模糊,故这次采用渐进的方 ...

  3. 三种迭代Java ArrayList方法及比较

    闲来无事,研究一下Java Collection,首先是ArrayList. 通过三种方式遍历了长度为100000的ArrayList. import java.util.*; public clas ...

  4. 冒泡排序算法的C++,Java和Python实现和冒泡排序算法三种语言效率的比较

    冒泡排序原理: 这一篇百度经验讲得很好,我不多说了 https://jingyan.baidu.com/article/6525d4b13f920bac7d2e9484.html 他讲的是C语言,没有 ...

  5. rabbitmq direct、fanout、topic 三种Exchange java 代码比较

    Producer端 1.channel的创建 无论是才用什么样的Exchange,创建channel代码都是相同的,如下 ConnectionFactory factory = new Connect ...

  6. Java中获取键盘输入值的三种方法

    Java中获取键盘输入值的三种方法     Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...

  7. 三种方式上传文件-Java

    前言:负责,因为该项目他(jetty嵌入式开始SpringMvc)实现文件上传的必要性,并拥有java文件上传这一块还没有被曝光.并 Http 更多晦涩协议.因此,这种渐进的方式来学习和实践上载文件的 ...

  8. Java并发编程:Java创建线程的三种方式

    目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...

  9. Java的三种循环:1、for循环 2、while循环 3、do...while循环

    Java的三种循环 Java三种循环结构: 1.for循环 2.while循环 3.do...while循环 循环结构组成部分:1.条件初始化语句,2.条件判断语句 , 3.循环体语句,4.条件控制语 ...

随机推荐

  1. 使用RTTI为继承体系编写”==”运算符

    转载请注明出处:http://www.cnblogs.com/inevermore/p/4012079.html   RTTI,指的是运行时类型识别技术.   先看一个貌似无关的问题:   为继承体系 ...

  2. &lt;LeetCode OJ&gt; 155. Min Stack

    Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...

  3. CSS3:选择器

    CSS选择器的作用是找出某类元素,以便我们使用style元素或者外部样式表对这类元素设置样式. 基本选择器 选择器 含义 演示样例 描写叙述 * 选择全部元素 * { border: thin bla ...

  4. 如何突破PHP程序员的技术瓶颈分析

    来自:http://www.jb51.net/article/27740.htm 身边有几个做PHP开发的朋友,也接触到不少的PHP工程师,他们常疑虑自己将来在技术上的成长与发展,我常给他们一些建议, ...

  5. JFinal中json的使用

    之前Java开发一直使用的是经典的ssh,去年接触了jfinal,觉得jfinal的魅力非常之大,让我无法自拔,现在还深深地陷在其中. 简单的介绍一下jfinal,jfinal短小精悍,让java有了 ...

  6. 转:什么是Node.js?

    Node不是万能药!但的确能解决一些关键问题 学习Node不是一件轻松事儿,但你所收到的回报是对得起你的付出的.因为当下Web应用开发中的诸多难题唯有JavaScript才能解决. 目录 专家们的警告 ...

  7. static 修饰的变量在程序中容易出现的问题

    package lianxi; public class StaticTest {    int a = 0;    static int b =0;    StaticTest(){         ...

  8. Eclipse注释模板设置

    设置注释模板的入口: Window->Preference->Java->Code Style->Code Template 然后展开Comments节点就是所有需设置注释的元 ...

  9. shadow密码文件

    登录Linux会要求输入用户名和密码.通常本地文件中会存储一份用户密码,并与用户输入对比,如果相同就允许用户登录.起初用户密码存储与/etc/passwd中,但由于/etc/passwd必须供所有用户 ...

  10. 华为nova3超级慢动作酷玩抖音,没有办法我就是这么强大!

    华为nova3超级慢动作酷玩抖音,没有办法我就是这么强大! 在华为最新发布的nova 3手机上,抖音通过华为himedia SDK集成了60fps.超级慢动作等华为媒体开放能力,在加持这些能力后,抖音 ...