排序_1.冒泡排序

冒泡排序

 冒泡排序(BubbleSort)是一種流行的排序算法,這個排序過程就像一個個向上(向右)冒泡的氣泡,最輕的氣泡先冒上來(到達R[n]位置),較重的氣泡後冒上來,因此形象的稱之爲冒泡排序.

Bubble_sort

  • 對R[1]~R[n]這n個記錄的冒泡排序過程:
    第一趟從第一個記錄R[1]開始到第n個記錄R[n]爲止,對(n- 1個對)相鄰的兩個記錄進行比較,若與排序要求相逆,則交換兩者的位置.
    這樣,經過一趟的比較,交換後,具有最大關鍵值的記錄就會被交換到R[n]位置.
    第二趟從第一個記錄R[1]開始到n - 1個記錄R[n-1]爲止繼續重複上述的比較與交換,這樣具有次大關鍵字的記錄就被交換到R[n-1]位置.
    如此重複,在經過n - 1 趟這樣的比較與交換之後,R[1]~R[n]這n個記錄已按關鍵字有序.

  • 化簡得:

設數組長度爲N。
1. 比較相鄰的前後二個數據,如果前面數據大於後面的數據,就將二個數據交換。
2. 這樣對數組的第0個數據到N-1個數據進行一次遍歷後,最大的一個數據就“沉”到數組第N-1個位置。
3. N=N-1,如果N不爲0就重複前面二步,否則排序完成。

冒泡排序視頻演示 備份鏈接1 備份鏈接2

過程演示:

首先:
       a[0]  a[1]  a[2]  a[3]  a[4]  a[5]  a[6]  a[7]  a[8]  a[9]
     3     0     1     8     7     2     5     4     6     9
第一步:
                                                                        //a[0] 比較 a[1] , 3 <---> 0,大,交換,得:
     0     3     1     8     7     2     5     4     6     9
                                                                        //a[1]   比較 a[2] , 3<--->1,大,交換,得:
     0     1     3     8     7     2     5     4     6     9
                                                                        //a[2]   比較 a[3] , 3<---> 8,小,不變,得:
     0     1     3     8     7     2     5     4     6     9
                                                                        //a[3]   比較 a[4] ,  8<---> 7,大,交換,得:
     0     1     3     7     8     2     5     4     6     9
                                                                        //a[4]   比較 a[5] ,  8<---> 2,大,交換,得:
     0     1     3     7     2     8     5     4     6     9
                                                                        //a[5]   比較 a[6] ,  8<---> 5,大,交換,得:
     0     1     3     7     2     5     8     4     6     9
                                                                        //a[6]   比較 a[7] ,  8<---> 4,大,交換,得:
     0     1     3     7     2     5     4     8     6     9
                                                                        //a[7]   比較 a[8] ,  8<---> 6,大,交換,得:
     0     1     3     7     2     5     4     6     8     9
                                                                        //a[8]   比較 a[9] ,  8<---> 9,小,不變,得:
     0     1     3     7     2     5     4     6     8     9

    這時,經過一次遍歷,我們得到了最大值已經被冒(放置)在最右邊,接下來,重複這樣的操作,到n-1的位置,得到次大.
    
第二次:
       a[0]  a[1]  a[2]  a[3]  a[4]  a[5]  a[6]  a[7]  a[8]  a[9]
     0     1     3     7     2     5     4     6     8     9
                                                                        //a[0] 比較 a[1] , 0 <---> 3,小,不變,得:
     0     1     3     7     2     5     4     6     8     9
                                                                        //a[1] 比較 a[2] , 1 <---> 3,小,不變,得:
     0     1     3     7     2     5     4     6     8     9
                                                                        //a[2] 比較 a[3] , 3 <---> 7,小,不變,得:
     0     1     3     7     2     5     4     6     8     9
                                                                        //a[3] 比較 a[4] , 7 <---> 2,大,交換,得:
     0     1     3     2     7     5     4     6     8     9
                                                                        //a[4] 比較 a[5] , 7 <---> 5,大,交換,得:
     0     1     3     2     5     7     4     6     8     9
                                                                        //a[5] 比較 a[6] , 7 <---> 4,大,交換,得:
     0     1     3     2     5     4     7     6     8     9
                                                                        //a[6] 比較 a[7] , 7 <---> 6,大,交換,得:
     0     1     3     2     5     4     6     7     8     9
                                                                        //a[7] 比較 a[8] , 7 <---> 8,小,不變,得:
     0     1     3     2     5     4     6     7     8     9
  
  ...
    我們可以看到,通過第二次,我們得到了次大元素並放入右邊倒數第二個位置上,我們若繼續重複,通過得到剩餘元素中最大值,可以得到整個元素組裏大小排列出來的次序.即可完成排序過程.   

程序代碼:

按照此定義,我們很容易寫出冒泡排序的程序代碼:

void BubbleSort1(int *a, int size)
{
    if(NULL == a || size < 0)
    {
        return;
    }
    int i = 0 ;
    int j = 0 ;
    int n = size;
    for(i = 0; i < n; i++)
    {
        for(j = 1; j < n - i; j++)
        {
            if(a[j-1] > a[j])
            {
                Swap(&a[j-1], &a[j]);
            }
        }
    }
}

即是將元素依次比較,若反序則交換.
我們可以看出,這樣的流程會有很多重複.那麼我們該怎麼樣進行優化呢?

如果是一個已經排好序的序列使用上述的方案進行排序的話,則在第一次的循環中則不會出現交換的過程(因爲前一個數據的值總是小於後一個數據),所以我們以是否發生了交換作爲排序是否結束的標誌。及如果一輪排序中並沒有發生交換過程則說明當前的序列是已序的。

0 1 2 3 5 8 9 4 6 7 
比如這個序列,基本有序,當我們排好後面的元素後,前面已經排好序,那麼我們就可以少進行比較.
我們可以設置一個標誌,如果這一趟發生了交換,則爲true,否則爲false。如果明顯如果有一趟沒有發生交換,說明排序已經完成。

#define TRUE 1
#define FALSE 0

typedef unsigned char Boolean;

void BubbleSort2(int *a, int size)
{
    if(NULL == a || size < 0)
    {
        return;
    }
    int j = 0 ;
    int n = size;
    Boolean flag = TRUE;
    while(flag)
    {
        flag = FALSE;
        for(j = 1; j < n; j++)
        {
            if(a[j-1] > a[j])
            {
                Swap(&a[j-1], &a[j]);
                flag = TRUE;
            }
        }
        n--;
    }
}

進一步優化,可以一個標記flag來表示當前的狀態,在每輪比較的開始把flag置爲0,則代表沒有發生排序,如果發生了排序,則把flag值爲1,在下次的循環中繼續進行比較。
如果有100個數的數組,僅前面10個無序,後面90個都已排好序且都大於前面10個數字,那麼在第一趟遍歷後,最後發生交換的位置必定小於10,且這個位置之後的數據必定已經有序了,記錄下這位置,第二次只要從數組頭部遍歷到這個位置就可以了。

void BubbleSort3(int *a, int size)
{
    if(NULL == a || size < 0)
    {
        return;
    }
    int j = 0 ;
    int n = size;
    int flag = n;
    while(flag > 0)
    {
        n = flag;
        flag = 0;
        for(j = 1; j < n; j++)
        {
            if(a[j-1] > a[j])
            {
                Swap(&a[j-1], &a[j]);
                flag = j;
            }
        }
    }
}

Alog

功能檢測

  • 檢測代碼:
int main()
{
    int i =0;
    int a[] = {3,0,1,8,7,2,5,4,6,9};
    int n = sizeof(a)/sizeof(a[0]);
    BubbleSort1(a, n);
//  BubbleSort2(a, n);
//  BubbleSort3(a, n);
    printf("\n");
    for(i = 0; i < n ; ++i)
    {
        printf("%3d",a[i]);
    }
    printf("\n");
    return 0;
}
  • 運行結果:
root@aemonair:~/Desktop# cc.sh BubbleSort.c 
Compiling ...
-e CC      BubbleSort.c -g -lpthread
-e         Completed .
-e         Sat Jul 23 18:42:01 CST 2016
root@aemonair:~/Desktop# ./BubbleSort 

  0  1  2  3  4  5  6  7  8  9

冒泡排序畢竟是一種效率低下的排序方法,在數據規模很小時,可以採用。數據規模比較大時,最好用其它排序方法。


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