• 1. 冒泡与选择排序及其比较


    冒泡排序

    1. 思想

      冒泡排序(Bubble Sort)是一种交换排序,基本思路是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止

     

    2. 实现

    2.1 初学常用的一种

    public static <T extends Comparable<? super T>> void BubbleSort(T[] a) {
      int length = a.length;
      for (int i = 0; i < length; i++) {
        for (int j = i+1; j < length; j++) {
          if (a[i].compareTo(a[j]) > 0) {
            Object obj = a[i];
            a[j] = a[i];
            a[i] = (T)obj;
          } // end if
        } // end for
      } // end for
    } // end BubbleSort

      缺陷:每一次内循环结束时,对其余的关键字没有帮助,甚至把原来靠近正确排序位置的记录交换到较远的地方。即,算法是低效的。

     

     

    2.2 正宗的冒泡排序

    public static <T extends Comparable<? super T>> void BubbleSort(T[] a) {
      int length = a.length;
      for (int i = 0; i < length - 1; i++) {
        for (int j = length - 2; j >= i; j--) {
          if (a[j].compareTo(a[j+1]) > 0) {
            Object obj = a[i];
            a[i] = a[j];
            a[j] = (T)obj;
          } // end if
        } // end for
      } // end for
    } // end BubbleSort

      

      显然这一算法比之前的实现要有效,图中较小的数字如同气泡慢慢浮到上面,因此将此算法命名为冒泡排序。 

     

    2.3 冒泡排序的优化

      对于已经有序或接近有序的集合时,会进行很多次不必要的循环比较,为此,需要改进实现,设置一个flag记录在一次循环比较中是否有交换操作,如果没有说明集合已经有序。

    public static <T extends Comparable<? super T>> void BubbleSort(T[] a) {
      int length = a.length;
      boolean flag = true;  // 用flag作为标记
      for (int i = 0; (i < length - 1) && flag; i++) {
        flag = false;
        for (int j = length - 2; j >= i; j--) {
          if (a[j].compareTo(a[j+1]) > 0) {
            Object obj = a[i];
            a[i] = a[j];
            a[j] = (T)obj;
            flag = true;     // 有数据交换则为true
          } // end if
        } // end for
      } // end for
    } // end BubbleSort

     

    2.4 冒泡排序复杂度分析

      最好的情况下,也就是数组有序时,根据最后改进的代码,需要比较n-1次关键字,没有数据交换,时间复杂度为O(n)最坏的情况下,即待排序记录全为倒序,此时比较1+2+3+4+…+(n-1) = n(n-1)/2次,并作等数量级的记录移动。所以时间复杂度为O(n2)。

     

    简单选择排序

    1. 思想

      冒泡排序的思想就不断地在交换,通过交换完成最终的排序。这种方式太繁琐,可不可以在确定位置的时候在交换,减少交换操作,完成只交换一次就完成相应关键字的排序定位?这就是选择排序的初步思想。

     

    2. 排序算法

      简单选择排序Simple Selection Sort)就是通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1 ≤ i ≤ n)个记录交换。

    // simple selection sort
    public static <T extends Comparable<? super T>> void SelectSort(T[] a) {
      int length = a.length;
      for (int i = 0; i < length - 1; i++) {
        int min = i;
        for (int j = i+1; j < length; j++) {
          if (a[min].compareTo(a[j]) > 0) {
            min = j;
          } // end if
        } // end for
        if (i != min) {
          Object obj = a[min];
          a[min] = a[i];
          a[i] = (T)obj;
        } // end if
      } // end for
    } // end SelectSort

     

    3. 简单选择排序复杂度分析

      从简单选择排序过程看,最大的特点是减少了移动数据的次数,这样节约了时间。无论最好还是最差的情况下,比较次数都是一样的,i趟要比较n-i次关键字,共需要比较(n-1)+(n-2)+…+2+1=n(n-1)/2次,最好情况下,即有序时,交换0次,最坏情况下,即逆序时,交换n-1次。最终排序时间为比较和移动的总和,时间复杂度为O(n2)。

    尽管与冒泡排序同为O(n2),但简单选择排序的性能还是要略优于冒泡排序。(下列比较却不是!)

     

    冒泡与选择排序对比

    import java.util.Arrays;
    /**
     * sort for Array
     * @author Administrator
     */
    public class Sort {
      // 非标准的冒泡排序,最简单的交换排序!(让每一个关键字,都和它后面的每一个关键字比较,如果大则交换)
      public static void BubbleSort1(int[] a) {
        int length = a.length;
        for (int i = 0; i < length; i++) {
          for (int j = i+1; j < length; j++) {
            if (a[i] > a[j]) {
              int obj = a[i];
              a[i] = a[j];
              a[j] = obj;
            } // end if
          } // end for
        } // end for
      } // end BubbleSort
    
      //  标准冒泡排序
      public static void BubbleSort2(int[] a) {
        int length = a.length;
        for (int i = 0; i < length - 1; i++) {
          for (int j = length - 2; j >= i; j--) {
            if (a[j] > a[j+1]) {
              int obj = a[j];
              a[j] = a[j+1];
              a[j+1] = obj;
            } // end if
          } // end for
        } // end for
      } // end BubbleSort
    
      public static void BubbleSort3(int[] a) {
        int length = a.length;
        boolean flag = true;  // 用flag作为标记
        for (int i = 0; (i < length - 1) && flag; i++) {
          flag = false;
          for (int j = length - 2; j >= i; j--) {
            if (a[j] > a[j+1]) {
              int obj = a[j];
              a[j] = a[j+1];
              a[j+1] = obj;
              flag = true;     // 有数据交换则为true
            } // end if
          } // end for
         } // end for
      } // end BubbleSort
    
      // simple selection sort
      public static void SelectSort(int[] a) {
        int length = a.length;
        for (int i = 0; i < length - 1; i++) {
          int min = i;
          for (int j = i+1; j < length; j++) {
            if (a[min] > a[j]) {
              min = j;
            } // end if
          } // end for
          if (i != min) {
            int obj = a[min];
            a[min] = a[i];
            a[i] = obj;
          } // end if
        } // end for
      } // end SelectSort
    
      public static void main(String[] args) {
        // 随机生成50000、50_0000的整数
        int[] a = new int[50_0000];
        for (int i = 0; i < a.length; i++) {
          a[i] = (int)(Math.random() * 500);
          //System.out.print(a[i] + " ");
        }
        // System.out.println();
        // 保证各个排序算法使用的数据一样
        int[] a2 = Arrays.copyOf(a, a.length);
        int[] a3 = Arrays.copyOf(a, a.length);
        int[] a4 = Arrays.copyOf(a, a.length);
        Date d1
    = new Date();     BubbleSort1(a); // 最常用的初学实现 50000:919,962,1032 500000:59425,60701,59811     System.out.println(new Date().getTime() - d1.getTime());     Date d2 = new Date();     BubbleSort2(a2); // 标准冒泡 50000:5332,5300,5957 500000:491104,480838,478621     System.out.println(new Date().getTime() - d2.getTime());     Date d3 = new Date();     BubbleSort3(a3); // 改进冒泡 50000: 5477,5648,5696 500000:526451,522458,503981     System.out.println(new Date().getTime() - d3.getTime());     Date d4 = new Date();     SelectSort(a4); // 50000: 1118,1256,1076 500000:107144,95680,94796     System.out.println(new Date().getTime() - d4.getTime());   } } // end Sort

      可以看出对于随机数组,常用的冒泡性能最好,接下来是简单选择排序,标准冒泡和改进的冒泡效率不如初学常用的冒泡高。改进的冒泡排序适合于接近有序或已经有序的情况。

  • 相关阅读:
    java图书管理系统界面版本+mysql数据库
    java数组实现的超市管理系统(控制台)
    Action<T>和Func<T>委托事例
    简单的委托示例
    使用静态方法CreateInstance()创建数组
    Span复习
    与预定义类型的用户类型强制转换
    实现自定义的索引运算符
    比较运算符的重载
    算术运算符的重载
  • 原文地址:https://www.cnblogs.com/datamining-bio/p/9715774.html
Copyright © 2020-2023  润新知