zoukankan      html  css  js  c++  java
  • 【DS】排序算法之冒泡排序(Bubble Sort)

    一、算法思想

        冒泡排序是排序算法中比较有意思的一种排序方法,也很简单。其算法思想如下:

    1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。

    2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

    3)针对所有的元素重复以上的步骤,除了最后一个。

    4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

    二、算法示意图

         这幅图形象的展示了冒泡的过程,最左边一列,从下往上显示了等待排序的数列,最后一列则显示了冒泡排序的最终结果。每一列阴影的部分代表等待排序的数列,黄色部分表示排序完成的部分,冒泡过程中不需要涉及黄色部分,我们解释一下第二列的形成过程:

         第二列在冒泡过程中(从下往上看),首先比较2和3,2<3,则交换;比较3和4,4>3,不需要交换;比较4和9,9>4,不需要交换,比较1和9,1<9,交换;比较5和9,5<9,交换;比较7和9,7<9,交换;比较6和9,6<9,交换;比较8和9,8<9,交换。这样就形成了第二列。第二列形成以后,9,也就是最后的数字已经是最大的了,第二趟这样进行形成第三列的时候,就不需要进行到9了。

         每一趟冒泡,都是将灰色数列部分中最大的数字选择出来放到黄色部分的最下层,由此形成下一列,最大数字的选择是通过数字的交换来完成的——算法会从数列的最前端开始往后遍历,如果发现某一个数比它前面的数字小,就会进行交换,把较大的数字往后移动。由此不断进行,就可以将最大的数字移动到数列灰色部分的最后。

    三、Java代码

     1 //@wiki
     2 public class BubbleSort extends Sort {
     3     public static void sort(int[] array) {
     4         int temp = 0;
     5         for (int i = array.length - 1; i > 0; --i) {
     6             for (int j = 0; j < i; ++j) {
     7                 if (array[j + 1] < array[j]) {
     8                     temp = array[j];
     9                     array[j] = array[j + 1];
    10                     array[j + 1] = temp;
    11                 }
    12             }
    13         }
    14     }
    15 }

    四、算法复杂度

          从上面的Java代码来看,第7行的比较是一定会进行的,假设数组元素是n,则进行的次数是:n*(n-1)/2。因为j是从0~i-1,而i是从n-1~1,所以简单计算就可以得出以上的结果。

          最差的情况当然是每次都执行if条件判断,并且执行其中的8,9,10三行语句,整体复杂度为4*n^2。出现最坏的情况就是一开始数列是倒叙排列的,即按照从大到小的顺序排列的,导致每一次比较都需要交换。

          在本代码中,最好的情况其实不能达到,我们去看示意图,我们发现五列已经完成了排序,第6,7,8列的排序过程其实可以省略。所以,冒泡排序可以优化,我们增加一个flag,当一趟冒泡完成时我们发现没有发生交换行为,就可以终止冒泡了,其代码如下:

     1 public class BubbleSort extends Sort {
     2     public static void sort(int[] array) {
     3         int temp = 0;
     4         for (int i = array.length - 1; i > 0; --i) {
     5             boolean exchange = false;
     6             for (int j = 0; j < i; ++j) {
     7                 if (array[j + 1] < array[j]) {
     8                     exchange = true;
     9                     temp = array[j];
    10                     array[j] = array[j + 1];
    11                     array[j + 1] = temp;
    12                 }
    13             }
    14             if(!exchange)
    15                 return;
    16         }
    17     }
    18 }

          如上,这样,我们可以将最好的复杂度降低为n,情况出现在数列一开始就是从小到大排列的时候,只需要遍历一边,exchange始终为false,直接返回,这样就可以得到最好的时间复杂度,为O(n),因此平均时间复杂度为O(n^2)

          空间复杂度非常容易,由代码可以看出来,只需要一个位置temp用于交换即可,因此是O(1)

  • 相关阅读:
    BZOJ_1712_[Usaco2007 China]Summing Sums 加密_矩阵乘法
    BZOJ_2693_jzptab_莫比乌斯反演
    BZOJ_5296_[Cqoi2018]破解D-H协议_BSGS
    BZOJ_5301_[Cqoi2018]异或序列&&CF617E_莫队
    前端开发框架对比
    现在企业流行的java框架技术
    尼古拉斯·沃斯
    算法和流程图
    Java中DAO的实现
    java中的DAO设计模式
  • 原文地址:https://www.cnblogs.com/lqminn/p/3649341.html
Copyright © 2011-2022 走看看