排序——冒泡排序法

1、冒泡排序法概述算法

    冒泡排序法的基本思想是:對待排序記錄關鍵字從後往前(逆序)進行多遍掃描,當發現相鄰兩個關鍵字的次序與排序要求的規則不符時,就將這兩個記錄進行交換。這樣,關鍵字較小的記錄將逐漸從後面向前面移動,就像氣泡在水中向上浮同樣,因此該算法也稱爲氣泡排序法。(提示:冒泡排序法也可以使較大的記錄排在前面)
    假設須要排序的記錄有n個,其關鍵字保存在數組a中,使用冒泡排序法,需對數組a進行n-1次掃描,完成排序操做,具體過程以下:
(1)將A[n]與A[n-1]進行比較,若A[n]<A[n-1],則交換兩元素的位置。
(2)修改數組下標,使須要比較的兩個元素爲A[n-1]和A[n-2],重複步驟1,對這兩個元素進行比較。重複這個過程,直到對A[2]和A[1]進行比較完爲止。完成第1遍掃描,以下圖所示。編程

3)通過第1遍掃描後,最小的元素已經像氣泡同樣「浮」到最上面,即位於元素A[1]中了。接下來重複前面的步驟,進行第2遍掃描,只是掃描到A[3]與A[2]進行比較完爲止(由於A[1]中已是最小的數據,不用再進行比較)。
(4)經過n-1遍掃描,前n-1個數都已經排序完成,最後一個元素A[n]確定就是最大的數了。至此,完成排序操做。(提示:在以上描述中,爲了讓讀者容易理解,假設數組元素是保存在A[1]~A[n]中的,因爲C語言的數組元素下標是從0開始的,所以,須要修改數組的下標)數組


下面以一組待排序的數據演示冒泡排序的過程,假設有6個須要排序的數據序列以下:
69,65,90,37,92,6
經過冒泡排序法對這6個數據進行排序,其排序過程以下圖所示。函數


第1遍從下向上掃描,首先對最後兩個元素A[5]和A[4]進行比較,因92>6,將6上浮到A[4],92下沉到A[5]。接着將A[4]中的6和A[3]比較,6仍然較小,繼續上浮至A[3]……這樣通過n-1次比較,6上浮到A[0],完成第1遍掃描。此時A[0]中保存着當前數列中的最小數。完成最小數的冒泡過程。測試

第2遍掃描仍然從A[5]開始,至A[1]時結束,將37上浮到A[1]。
相似的方法,在第3遍掃描時,65上浮到A[2]中,至此,全部數都已按從小到大的順序排列,但程序還須要進行第4遍和第5遍的掃描,由於程序並不知道後面的數據是否爲有序的。code

2、冒泡排序法實現排序

(1)冒泡排序法內存

void BubbleSort(int a[], int n)
{
    int i, j, t;

    for (i=0; i<n; i++) {
        for (j=n-1; j>i; j--) {
            if (a[j-1] > a[j]) {
                t = a[j-1];
                a[j-1] = a[j];
                a[j] = t;
            }
        
        }
        
        printf("第%d遍:", i+1);
        for (j=0; j<n; j++)
            printf("%d ", a[j]);
        printf("\n");
    }

}

(2)數組顯示io

void ShowData(int arr[], int n)
{
    int i;
    for (i=0; i<n; i++)
        printf("%d ", arr[i]);
    printf("\n");

    return;
}

(3)冒泡排序法測試class

#include <stdio.h>
#define ARRAYLEN 6

int main(int argc, char *argv[])
{
    int i;
    int a[ARRAYLEN] = {69, 65, 90, 37, 92, 6};

    printf("原數據:");
    ShowData(a, ARRAYLEN);

    BubbleSort(a, ARRAYLEN);
    printf("排序後:");
    ShowData(a, ARRAYLEN);

    return 0;
}

(4)運行結果

3、冒泡排序法改進

    從上面的BubbleSort函數的過程能夠看出,使用冒泡排序法對n個數據進行排序,一共須要進行n-1次的比較。若是原本就是有順序的數據,也須要進行n-1次比較。這就形成了冒泡排序法的算法雖然簡單,但效率較差。
    爲了提高冒泡排序法的效率,可對BubbleSort函數進行改進,當在某一遍掃描時,發現數據都已經按順序排列了,就再也不進行後面的掃描,而結束排序過程。
    如何知道數據已經按順序排好了呢?從上圖能夠看出,當第3遍掃描後,數據已經按順序排列好了,第4遍掃描時將沒有數據進行交換。所以,能夠設置一個標誌變量flag,在每一遍掃描以前將其值設置爲0,在掃描數據過程當中,如有數據交換,則設置其值爲1。在一遍掃描完成以後,判斷flag的值,若其值爲0,表示在這一遍掃描中已經沒有數據進行交換,數據已經按順序排列,就不須要再進行後續的掃描了。


編程經驗:爲了提升排序效率,引進了一個標誌變量。即經過內存空間使用上的增多來使程序執行效率獲得提高,這稱爲「以空間換時間」。

(1)改進冒泡排序法的實現

void BubbleSortNew(int a[], int n)
{
    int i, j, t, flag=0;

    for (i=0; i<n; i++) {
        for (j=n-1; j>i; j--) {
            if (a[j-1] > a[j]) {
                t = a[j-1];
                a[j-1] = a[j];
                a[j] = t;
                flag = 1;
            }
        
        }
        
        printf("第%d遍:", i+1);
        for (j=0; j<n; j++)
            printf("%d ", a[j]);
        printf("\n");


        if (flag == 0)
            break;
        else 
            flag = 0;
    }

}

(2)改進冒泡排序法測試

#include <stdio.h>
#define ARRAYLEN 6

int main(int argc, char *argv[])
{
    int i;
    int a[ARRAYLEN] = {69, 65, 90, 37, 92, 6};

    printf("原數據:");
    ShowData(a, ARRAYLEN);

    BubbleSortNew(a, ARRAYLEN);
    printf("排序後:");
    ShowData(a, ARRAYLEN);

    return 0;
}

(3)運行結果

能夠看出來,當第3遍掃描後,數據已經按順序排列好了,第4遍掃描時將沒有數據進行交換,就再也不進行後面的掃描,而結束排序過程。

相關文章
相關標籤/搜索