冒泡排序法的原理是,每次比较相邻的两个元素,如果它们的顺序错误就把它们交换过来。

例如对4 3 6 2 7 1 5这7个数字进行从小到大的排序,从最左侧开始,首先比较4和3

因为是从小到大排序,4和3的顺序显然是错误的,交换他们,得到

接下来比较4和6

顺序是正确的,不需要任何操作。接下来进行下一步,比较6和2

6显然应该排在2的后面,怎么办?交换它们,得到

经过前面几步,已经可以总结出规律,那么接下来要做的比较依次是:

7 > 1? 得到 3 4 2 6 1 7 5

7 > 5? 得到

到此,7的右边已经没有数可以比较,第一轮排队结束。经过这一轮,已经成功的把最大的数,即7放在了最后。但是前面6个数的顺序还是不对,但是按照上面的思路很容易想到,对前面6个数再来一遍,即可把6放到倒数第二的位置。然后再对前面5个数重复逐个比较的步骤。。。

7个数字需要进行7-1=6次排队,每完成一轮排队,下一轮排队需要比较的数字个数减1,来看代码

  1. public class BubbleSort {
  2. public void sort(int... numbers) {
  3. //n个数执行n-1轮
  4. //每一轮后完成一个数字归位, 下一轮要比较的数字个数减1(所以内层循环是j < n - i)
  5. int n = numbers.length - 1;
  6. int t;
  7. for(int i = 0; i < n; i++) {
  8. for(int j = 0; j < n - i; j++) {
  9. if(numbers[j] > numbers[j + 1]) {
  10. t = numbers[j];
  11. numbers[j] = numbers[j + 1];
  12. numbers[j + 1] = t;
  13. }
  14. }
  15. }
  16. }
  17. }

测试

  1. public static void main(String[] args) {
  2. int[] numbers = new int[]{ 4, 3, 6, 2, 7, 1, 5 };
  3. System.out.print("before: ");
  4. for(int i = 0; i < numbers.length; i++) {
  5. System.out.print(numbers[i] + "  ");
  6. }
  7. System.out.println();
  8. new BubbleSort().sort(numbers);
  9. System.out.print("after: ");
  10. for(int i = 0; i < numbers.length; i++) {
  11. System.out.print(numbers[i] + "  ");
  12. }
  13. System.out.println();
  14. }

输出

  1. before: 4  3  6  2  7  1  5
  2. after: 1  2  3  4  5  6  7

冒泡排序的核心是两层嵌套的循环,时间复杂度是O(N^2),即对N个数排序,需要近似执行N的平方次。因为效率较低,实际开发中基本不会使用,但是因为简单易懂通常做为学习算法的入门案例。

如果用上面的代码对1 2 3 4 5 6 7做从小到大排列,会发现虽然数字已经排列好,但是程序还是要忠实的执行完全部两层循环。对这种情况,我们可以引入一个变量来记录一次内层循环中交换数字的个数,如果交换个数为0,则提前终止循环,在某些情况下可以提高效率。

  1. public void betterSort(boolean descend, int... numbers) {
  2. System.out.print("before: ");
  3. for(int i = 0; i < numbers.length; i++) {
  4. System.out.print(numbers[i] + "  ");
  5. }
  6. System.out.println();
  7. //n个数执行n-1轮
  8. //每一轮后完成一个数字归位, 下一轮要比较的数字个数减1(所以内层循环是j < n - i)
  9. int n = numbers.length - 1;
  10. int t;
  11. int flag = 0;
  12. for(int i = 0; i < n; i++) {
  13. for(int j = 0; j < n - i; j++) {
  14. if(descend) { //从大到小
  15. if(numbers[j] < numbers[j + 1]) {
  16. t = numbers[j];
  17. numbers[j] = numbers[j + 1];
  18. numbers[j + 1] = t;
  19. flag = 1;
  20. }
  21. } else {
  22. if(numbers[j] > numbers[j + 1]) {
  23. t = numbers[j];
  24. numbers[j] = numbers[j + 1];
  25. numbers[j + 1] = t;
  26. flag = 1;
  27. }
  28. }
  29. }
  30. if(flag == 0) {
  31. break;
  32. } else {
  33. flag = 0;
  34. }
  35. }
  36. System.out.print("after: ");
  37. for(int i = 0; i < numbers.length; i++) {
  38. System.out.print(numbers[i] + "  ");
  39. }
  40. System.out.println();
  41. }

增加一个变量需要额外占用内存空间,因此,这个方法是以空间换时间。

Java与算法之(1) - 冒泡排序的更多相关文章

  1. Java经典算法汇总之冒泡排序

    冒泡排序基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒.即:每当两相邻的数比较后发现它们的排序与排序要求相反时 ...

  2. java排序算法(四):冒泡排序

    java排序算法(四):冒泡排序 冒泡排序是计算机的一种排序方法,它的时间复杂度是o(n^2),虽然不及堆排序.快速排序o(nlogn,底数为2).但是有两个优点 1.编程复杂度很低.很容易写出代码 ...

  3. java排序算法之冒泡排序(Bubble Sort)

    java排序算法之冒泡排序(Bubble Sort) 原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2个数 ...

  4. java排序算法之冒泡排序和快速排序

    总结一下Java排序算法,以便记忆. 各类排序的时间复杂度: 排序方法 时间复杂度(平均) 时间复杂度(最坏) 时间复杂度(最好) 空间复杂度 稳定性 复杂性 直接插入排序 O(n2)O(n2) O( ...

  5. Java 排序算法-冒泡排序及其优化

    Java 排序算法-冒泡排序及其优化 什么是冒泡排序 基本写法 优化后写法 终极版本 源码及测试 什么是冒泡排序 这里引用一下百度百科上的定义: 冒泡排序(Bubble Sort),是一种计算机科学领 ...

  6. 算法相关——Java排序算法之冒泡排序(二)

    0. 前言 本系列文章将介绍一些常用的排序算法.排序是一个非常常见的应用场景,也是开发岗位面试必问的一道面试题,有人说,如果一个企业招聘开发人员的题目中没有排序算法题,那说明这个企业不是一个" ...

  7. 常用Java排序算法

    常用Java排序算法 冒泡排序 .选择排序.快速排序 package com.javaee.corejava; public class DataSort { public DataSort() { ...

  8. Hark的数据结构与算法练习之冒泡排序

    算法说明: 冒泡排序实际上是使用的最多的排序,逻辑是循环然后对相邻的数字进行比较,并交换数据. 例如有一个数组int[] arrayData = { 2, 3, 1, 5, 6, 7, 4, 65, ...

  9. Java经典算法四十例编程详解+程序实例

    JAVA经典算法40例 [程序1]   题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?   1.程 ...

随机推荐

  1. 批量下载google 字体小工具

    在项目开发中,我们经常用外国的框架,如bootstrap.nodejs.angularjs 时候经常要配套google 字体等资源, 但是由于国内网络原因,经常框架跑起来,网页在请求google 字体 ...

  2. Bash shell命令记录和CentOS的一些技巧

    ①CentOS的实用技巧: 一.按下ctrl+alt+F2可由图形界面切换至命令行(shell窗口),按下ctrl+alt+F1可由命令行切换至图形界面(前提是安装CentOS时软件选择项选择安装了图 ...

  3. Servlet过滤器简单探索

    过滤器的工作时机介于浏览器和Servlet请求处理之间,可以拦截浏览器对Servlet的请求,也可以改变Servlet对浏览器的响应. 其工作模式大概是这样的: 一.Filter的原理 在Servle ...

  4. Kotlin——最详细的常量、变量、注释的使用

    在Kotlin中的变量.常量以及注释多多少少和Java语言是有着不同之处的.不管是变量.常量的定义方式,还是注释的使用.下面详细的介绍Kotlin中的变量.常量.注释的使用.以及和Java的对比. 如 ...

  5. magento获取商品的图片

    获取商品的图片主要从catalog_product_entity_media_gallery 表中 该表中各列的属性代表 value_id:记录 ID,可以留空让数据库自动生成. attribute_ ...

  6. css3 UI元素状态伪类选择器

    选择器 说明 例子/备注 E:hover 当鼠标移到元素上元素所使用的样式 :hover{}或input:[type="text"]:hover{} E:active 当元素被激活 ...

  7. Java的演化-Java8实战笔记

    一个语言要想一直有活力,它也需要跟随着时代的变化去进步,Java作为一个古老的语言,它其实有太多的历史包袱,在改变的过程中需要考虑很多,但是它也在慢慢的演变,巩固自己的城墙,不让自己被遗忘在历史中(不 ...

  8. 读书笔记:《HTML5开发手册》-- 现存元素的变化

    继续学习HTML5语义化的内容,今天主要介绍一下,HTML5之前的元素经HTML5规范后的语义及一些使用示例. 一.cite HTML5对cite元素的定义进行了很大的修改,在HTML4中,cite元 ...

  9. longest valid parentheses方法归纳

    题目大意见leetcode,下面我稍微介绍下想到的三种方法: 方法一:不用栈去找匹配 建立一个数组l2表示匹配,然后i从0开始,看到 ( 就把l2对应的数值记为-1,直到看到 ),找到)以后,从当前i ...

  10. socket对象放在一个datagridview的row的tag里面在拿出来 为什么是已释放

     socket对象放在一个datagridview的row的tag里面在拿出来 为什么是已释放