1. 程式人生 > >氣泡排序的優化方案

氣泡排序的優化方案

為什麼要突然要講這個呢,因為之前被朋友問到的,剛開始一臉矇蔽,寫了那某多次氣泡排序,自己也沒想太多優化的問題。

所以Google了一下,其實優化的核心思想就是減少比較的次數,非常簡單。

普通的氣泡排序如下:

 static void BubbleSort1(int[] arr, int size)
    {
        int i = 0, j = 0;
        int count = 0;
        for (i = 0; i < size - 1; i++)//一共要排序size-1次
        {
            for (j = 0; j < size - 1 - i; j++)//選出該趟排序的最大值往後移動
            {
                if (arr[j] > arr[j + 1])
                {
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                }
                count++;
            }
        }
        //count計算比較的次數
        System.out.println("bubble 1 = "+count);
    }

 氣泡排序的最壞時間複雜度為O(n^2)。

 優化方案1:優化外層迴圈

//氣泡排序優化1
    static void BubbleSort2(int[] arr, int size)
    {
        int i = 0, j = 0;
        int count = 0;
        for (i = 0; i < size - 1; i++)//一共要排序size-1次
        {
            //每次遍歷標誌位都要先置為0,才能判斷後面的元素是否發生了交換
            int flag = 0;

            for (j = 0; j < size - 1 - i; j++)//選出該趟排序的最大值往後移動
            {
                if (arr[j] > arr[j + 1])
                {
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    flag = 1;//只要有發生了交換,flag就置為1
                }
                count++;
            }

            //判斷標誌位是否為0,如果為0,說明後面的元素已經有序,就直接return
            if (flag == 0)
            {
                break;
            }
        }

        System.out.println("bubble 2 = "+count);

    }

 在上面給出的演算法中,引入一個標籤flag,在每趟排序開始前,先將其置為0。若排序過程中發生了交換,則將其置為1。各趟排   序結束時檢查flag,若未曾發生過交換,說明此時的陣列已經是有序的了,則終止演算法,不再進行多餘的相鄰比較。

 優化方案2:優化內層迴圈

 //氣泡排序優化2
    static void BubbleSort3(int[] arr, int size)
    {
        int i = 0, j = 0;
        int k = size - 1,pos = 0;//pos變數用來標記迴圈裡最後一次交換的位置
        int count = 0;

        for (i = 0; i < size - 1; i++)//一共要排序size-1次
        {
            //每次遍歷標誌位都要先置為0,才能判斷後面的元素是否發生了交換
            int flag = 0;
            for (j = 0; j <k; j++)//選出該趟排序的最大值往後移動
            {
                if (arr[j] > arr[j + 1])
                {
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    flag = 1;//只要有發生了交換,flag就置為1
                    pos = j;//迴圈裡最後一次交換的位置 j賦給pos
                }
                count++;
            }
            k = pos;
            //判斷標誌位是否為0,如果為0,說明後面的元素已經有序,就直接return
            if (flag == 0)
            {
               break;
            }
        }
        System.out.println("bubble 3 = "+count);
    }

方案2 在 方案1的基礎下又進行了一次優化,方案2的演算法在每趟掃描中,記住最後一次交換髮生的位置lastExchange,(該位置之後的相鄰記錄均已有序)。下一趟排序開始時,R[1..lastExchange-1]是無序區,R[lastExchange..n]是有序區。這樣,一趟排序可能使當前無序區擴充多個記錄,因此記住最後一次交換髮生的位置lastExchange,從而減少排序的趟數。

總結

演算法複雜度比較:方案2 <= 方案1 <= 普通冒泡

參考:https://blog.csdn.net/yanxiaolx/article/details/51622286