排序算法之冒泡排序

前言

排序算法中最最常見也算是入門的一個排序算法就是冒泡排序。這篇文章我們就來好好地寫寫這個冒泡排序算法,以及冒泡排序呢的改進算法。

傳統冒泡算法

static int[] array = {100,1,5,4,11,2,20,18,89,34,20,34};
@Test
    public  void bubbleSortNormal(){
        int temp;
        int len = array.length;

        for(int i=0;i<len-1;i++){
            for(int j=1;j<len-i;j++){
                if(array[j-1]>array[j]){
                    temp = array[j-1];
                    array[j-1] = array[j];
                    array[j] = temp;
                }
            }
            System.out.print("第"+(i+1)+"輪排序結果:");
            display();
        }
    }

排序算法之冒泡排序
分析:
上面的算法代碼非常好理解,我們現在來分析一下這個算法的時間複雜度:
(N-1)+ (N-2)+ (N-3)+ ...1=N*(N-1)/2;
因爲只有在前面的元素比後面的元素大時才交換數據,所以交換的次數少於比較的次數。如果數據是隨機的,大概有一半數據需要交換,則交換的次數爲N^2/4(不過在最壞情況下,即初始數據逆序時,每次比較都需要交換)。
交換和比較的操作次數都與N^2成正比,由於在大O表示法中,常數忽略不計,冒泡排序的時間複雜度爲O(N^2)。
O(N^2)的時間複雜度是一個比較糟糕的結果,尤其在數據量很大的情況下。所以普通冒泡排序通常不會用於實際應用。

改進冒泡排序版本1

既然普通的冒泡排序只適合用於排序入門,那這冒泡排序是否可以進行改進進行實際應用呢?這裏我們就來進行冒泡排序改進。上面的比較次數非常的不合理,就算是正常的有序依然會進行比較N*(N-1)/2次,那我們就可以通過標記當前已經有序則停止進行後續無用的比較,跳出循環。具體代碼如下:

   static int[] array = {100,1,5,4,11,2,20,18,89,34,20,34};
   @Test
    public void bubbleSortPlusOne(){
        int temp;
        int len = array.length;
        for(int i=0;i<len-1;i++){
            boolean exchange = false;
            for(int j=1;j<len-i;j++){
                //如果前一位大於後一位,交換位置
                if(array[j-1]>array[j]){
                    temp = array[j-1];
                    array[j-1] = array[j];
                    array[j] = temp;

                    //發生了交換操作
                    if(!exchange){ exchange =true;}
                }
            }
            System.out.print("第"+(i+1)+"輪排序結果:");
            display();
            //如果上一輪沒有發生交換數據,證明已經是有序的了,結束排序
            if(!exchange){ break;}
        }
    }

排序算法之冒泡排序
分析:
加入標誌性變量exchange,用於標誌某一趟排序過程中是否有數據交換,如果進行某一趟排序時並沒有進行數據交換,則說明數據已經按要求排列好,可立即結束排序,避免不必要的比較過程。

進一步升級冒泡排序

上面的改進方法,是根據上一輪排序有沒有發生數據交換作爲標識,進一步思考,如果上一輪排序中,只有後一段的幾個元素沒有發生數據交換,是不是可以判定這一段不用在進行比較了呢?答案是肯定的。

    @Test
    public void bubbleSortImprovement(){
        int temp;
        int counter = 1;
        int endPoint = array.length-1;

        while(endPoint>0){
            int pos = 1;
            for(int j=1;j<=endPoint;j++){
                if(array[j-1]>array[j]){
                    temp= array[j-1];
                    array[j-1]= array[j];
                    array[j]= temp;

                    pos= j;
                }
            }
            endPoint= pos-1;

            System.out.print("第"+counter+"輪排序結果:");
            display();
            counter++;
        }
    }

排序算法之冒泡排序
分析:
設置一個pos指針,pos後面的數據在上一輪排序中沒有發生交換,下一輪排序時,就對pos之後的數據不再比較。

冒泡排序改進

我們是否可以通過正向找尋最大值,反向找尋最小值把這個排序完成呢?答案是肯定的,接下來我們通過算法進行分析:

@Test
    public void bubbleSortImprovementPlus(){
        int temp;
        int low = 0;
        int high = array.length-1;
        int counter = 1;
        while(low<high){

            for(int i=low;i<high;++i){
                if(array[i]>array[i+1]){
                    temp= array[i];
                    array[i]= array[i+1];
                    array[i+1]= temp;
                }
            }
            --high;

            for(int j=high;j>low;--j){
                if(array[j]<array[j-1]){
                    temp= array[j];
                    array[j]= array[j-1];
                    array[j-1]= temp;
                }
            }
            ++low;

            System.out.print("第"+counter+"輪排序結果:");
            display();
            counter++;
        }
    }

排序算法之冒泡排序
分析:
傳統的冒泡算法每次排序只確定了最大值,我們可以在每次循環之中進行正反兩次冒泡,分別找到最大值和最小值,如此可使排序的輪數減少一半。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章