• 排序算法——冒泡排序


    一、基本介绍

      冒泡排序(Bubble Sorting)的基本思想是:

        通过对待排序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就像水底的气泡一样逐渐向上冒。

    二、演示冒泡过程的例子(图解)

      

        总结图解过程

        (1)一共进行 数组的大小-1 次 大的循环

        (2)每一趟排序的次数在逐渐的减少

        (3)如果发现在某趟排序中,没有发生一次交换,可以提前结束冒泡排序,这就是优化。

    三、冒泡排序实现

      将五个无序的数:3,9,-1,10,-2 使用冒泡排序法将其排成一个从小到大的有序数列。

      演变过程:

     1         int[] arr = {3, 9, -1, 10, -2};
     2      int temp = 0;  //临时变量,用于交换数据
     3         
     4         //第一趟排序,就是将最大的数排在最后
     5         for (int j = 0; j < arr.length - 1 - 0; j++) {
     6             // 如果前面的数比后面的数大,进行交换
     7             if (arr[j] > arr[j+1]) {
     8                 temp = arr[j];
     9                 arr[j] = arr[j+1];
    10                 arr[j+1] = temp;
    11             }
    12         }
    13         System.out.println("第一趟排序结果:" + Arrays.toString(arr));
    14         
    15         
    16         //第二趟排序,就是把第二大的数排在倒数第二位
    17         for (int j = 0; j < arr.length - 1 - 1; j++) {
    18             if (arr[j] > arr[j+1]) {
    19                 temp = arr[j];
    20                 arr[j] = arr[j+1];
    21                 arr[j+1] = temp;
    22             }
    23         }
    24         System.out.println("第二趟排序结果:" + Arrays.toString(arr));
    25         
    26         //第三趟排序,就是把第三大的数排在倒数第三位
    27         for (int j = 0; j < arr.length - 1 - 2; j++) {
    28             if (arr[j] > arr[j+1]) {
    29                 temp = arr[j];
    30                 arr[j] = arr[j+1];
    31                 arr[j+1] = temp;
    32             }
    33         }
    34         System.out.println("第三趟排序结果:" + Arrays.toString(arr));
    35         
    36         //第四趟排序,就是把第四大的数排在倒数第四位
    37         for (int j = 0; j < arr.length - 1 - 1; j++) {
    38             if (arr[j] > arr[j+1]) {
    39                 temp = arr[j];
    40                 arr[j] = arr[j+1];
    41                 arr[j+1] = temp;
    42             }
    43         }
    44         System.out.println("第四趟排序结果:" + Arrays.toString(arr));

      封装成一个方法:

     1     // 将前面的冒泡排序算法,封装成一个方法
     2     // 冒泡排序的时间复杂度为 O(n^2)
     3     public static void bubbleSort(int[] arr) {
     4         int temp = 0;  //临时变量
     5         for (int i = 0; i < arr.length - 1; i++) {
     6             for (int j = 0; j < arr.length - 1 - i; j++) {
     7                 // 如果前面的数比后面的数大,进行交换
     8                 if (arr[j] > arr[j+1]) {
     9                     temp = arr[j];
    10                     arr[j] = arr[j+1];
    11                     arr[j+1] = temp;
    12                 }
    13             }
    14             
    15             System.out.println("第"+(i+1)+"趟排序结果:" + Arrays.toString(arr));
    16         }
    17     }

      测试:

     1 public class BubbleSort {
     2 
     3     public static void main(String[] args) {
     4         int[] arr = {3, 9, -1, 10, -2};
     5         
     6         // 测试一下冒泡排序的速度O(n^2),给80000个数据,测试
     7         // 创建要给 80000 个随机的数组
     8         int[] arr2 = new int[80000];
     9         for(int i = 0;i < 80000;i++) {
    10             arr2[i] = (int)(Math.random()*80000);
    11         }
    12         
    13         Date date1 = new Date();
    14         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    15         String date1String = format.format(date1);
    16         System.out.println("排序前的时间是="+date1String);
    17         
    18         //测试冒泡排序
    19         bubbleSort(arr2);
    20         
    21         
    22         Date date2 = new Date();
    23         String date2String = format.format(date2);
    24         System.out.println("排序后的时间是="+date2String);
    25 }

      

      可以看出冒泡排序对80000个数据进行排序,大概需要20秒左右的时间。

     四、优化

      优化:

        因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序。因此要在排序过程中设置一个标志 flag 判断元素是否进行过交换,从而减少不必要的比较。

        

        对于上面的排序可以发现,在第三趟排序的时候就已经是有序的,这时就可以跳出循环。所以可以标识一个变量,当某一趟排序时不再交换,这时就排序完成了。

        优化后的代码:

     1   //优化
     2     public static void bubbleSort2(int[] arr) {
     3         int temp = 0;  //临时变量
     4         boolean flag = false;   //定义一个标识变量,标识是否进行过交换
     5         for (int i = 0; i < arr.length - 1; i++) {
     6             for (int j = 0; j < arr.length - 1 - i; j++) {
     7                 // 如果前面的数比后面的数大,进行交换
     8                 if (arr[j] > arr[j+1]) {
     9                     flag = true;
    10                     temp = arr[j];
    11                     arr[j] = arr[j+1];
    12                     arr[j+1] = temp;
    13                 }
    14             }
    15             
    16             if (!flag) {
    17                 break;
    18             } else {
    19                 flag = false;
    20             }
    21             
    22             System.out.println("第"+(i+1)+"趟排序结果:" + Arrays.toString(arr));
    23         }
    24     }

     

  • 相关阅读:
    HttpWebRequest用ip代理Timeout和ReadWriteTimeout失效不听话问题
    C# CefSharp CachePath 碰到的坑
    连接gitee的两种方式
    .net core 5.0 之使用多环境
    .net core 第三方登录关于AddOAuth
    .net core 5.0 之IHttpClientFactory
    .net core 5.0 之 五种Filter
    .net core 5.0 之自定义中间件
    有用的和不为人知的Java特性
    Google Authenticator 备份密钥/导出
  • 原文地址:https://www.cnblogs.com/niujifei/p/11795020.html
Copyright © 2020-2023  润新知