排序演算法之冒泡排序

來源:互聯網
上載者:User

作者:hustwing         hustwing@126.com  MSN: hustwing@hotmail.com

冒泡排序算是排序演算法中比較有名的了,初學排序之時,我們經常拿它來開刀,大學時學習C語言,老師講的第一個排序演算法就是冒泡。然而它的效率低也是眾所周知的。只要說起冒泡,大家無不皺起眉頭,彷彿用了冒泡就說明你這個人完全沒有考慮效率。但是,其實又有多少人真的理解冒泡呢?

我之前根本沒有準備在Algorithm裡專門為冒泡寫一篇文章,但是當我發覺我需要大概大半天的時間才能弄懂它時,我才覺得還是有必要把我所學的關於冒泡演算法的知識總結一下。

起初,我搞混了冒泡排序跟選擇排序,後來到網上一查,發現大概有一半的人跟我一樣弄混了這兩種演算法。下面是這兩種演算法的基本思想:

選擇法排序(升序)
基本思想:
  1)對有n個數的序列(存放在數組a(n)中),從中選出最小的數,與第1個數交換位置;
  2)除第1 個數外,其餘n-1個數中選最小的數,與第2個數交換位置;
  3)依次類推,選擇了n-1次後,這個數列已按升序排列。

冒泡法排序(升序)
基本思想:(將相鄰兩個數比較,小的調到前頭)
1)有n個數(存放在數組a(n)中),第一趟將每相鄰兩個數比較,小的調到前頭,經n-1次兩兩相鄰比較後,最大的數已“沉底”,放在最後一個位置,小數上升“浮起”;
2)第二趟對餘下的n-1個數(最大的數已“沉底”)按上法比較,經n-2次兩兩相鄰比較後得次大的數;
3)依次類推,n個數共進行n-1趟比較,在第j趟中要進行n-j次兩兩比較。

從上面的基本思想可以看出,冒泡法與選擇法最大的不同是,冒泡法是相鄰的數比較交換,而選擇法則是其它所有的數與某個特定位置的數比較交換。反映到代碼上就是下面的區別;

---------------------------------簡單選擇排序-------------------------------------

void SimpleSelectSort(int* const arr,int arrLength)
{
    int i,j,imin,temp;

    for (i = 0; i    {
        for (j = i+1; j        {
            if (arr[i] > arr[j])//注意這一行,非相鄰比較,選擇排序
            {
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

---------------------------------簡單冒泡排序-------------------------------------

void SimpleBubbleSort(int* const arr,int arrLength)
{
    int i,j,temp;
    for (i = 0; i     {
        for (j = 0;j        {
            if (arr[j] > arr[j+1])//注意這一行,是相鄰比較
            {
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

------------------------------------------------------------------------------------------

為其正名之後,我們再來看看它還有些什麼變種,呵呵。按照其基本思想,我們可以這樣設想:設若是升序排列,那我們就有兩種選擇,一種是兩兩相鄰比較,選擇每次將最小的數"冒"到最左邊來(數組的最前端),這叫做前向冒泡或者正向冒泡!也可以選擇每次將最大的數"冒"到最右邊去,這個相應叫做後向冒泡或反向冒泡。當然,聰明人還想到了第三種方法,那就是兩邊同時"冒",一次冒出一個最大的和最小的,然後再一次冒出一個次大的和次小的(雙向冒泡!)!事實證明這的確是個不錯的想法,至少從效率上說是這樣。

下面是這三種冒泡演算法的具體實現代碼,代碼裡包含了與效能比較有關代碼,只有迴圈那部分的代碼(粗體)是冒泡演算法的具體實現,在文章的最後,給出關於這三種演算法的效能測試,當然,這個資料是我自己測試得出,不見得絕對客觀的。

--------------------------------------------------------------------三種冒泡演算法---------------------------------------------------------------------

SORT_PERFORMANCE ForwardBubbleSort(int* const arr,int arrLength)
{
    int i,j,temp;
    bool flag = false;
    unsigned int circuTimes = 0,swapTimes = 0;
    clock_t start,end;
    SORT_PERFORMANCE sort_perform;

    start = clock();
   for (i = 0; i     {
        for (j = arrLength - 1;j > i; j--)
        {
            circuTimes++;
            if (arr[j]             {
                temp = arr[j];
                arr[j] = arr[j-1];
                arr[j-1] = temp;
                flag = true;
                swapTimes++;
            }
        }
        if (!flag)
        {
            break;
        }
    }

    end = clock();
    sort_perform.CircuTimes = circuTimes;
    sort_perform.MilliSeconds = end - start;
    sort_perform.SwapTimes = swapTimes;
    return sort_perform;
}
SORT_PERFORMANCE BackwardBubbleSort(int* const arr,int arrLength)
{
    int i,j,temp;
    bool flag = false;
    unsigned int circuTimes = 0,swapTimes = 0;
    clock_t start,end;
    SORT_PERFORMANCE sort_perform;
    start = clock();
    for (i = 0; i     {
        for (j = 0;j        {
            circuTimes++;
            if (arr[j] > arr[j+1])
            {
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
                flag = true;
                swapTimes++;
            }
        }
        if (!flag)
        {
            break;
        }
    }
    end = clock();
    sort_perform.CircuTimes = circuTimes;
    sort_perform.MilliSeconds = end - start;
    sort_perform.SwapTimes = swapTimes;
    return sort_perform;
}
SORT_PERFORMANCE DoubleDirectionBubbleSort(int* const arr,int arrLength)
{
    int temp; 
    int left = 0; 
    int right =arrLength -1; 
    int t = 0,i; 
    unsigned int circuTimes = 0,swapTimes = 0;
    clock_t start,end;
    SORT_PERFORMANCE sort_perform;
    start = clock();
    do
    {
        //先正向冒泡
        for (i = right; i > left; i--)
        {
            circuTimes++;
            if (arr[i-1] > arr[i] )
            {
                temp = arr[i -1];
                arr[i -1] = arr[i];
                arr[i] = temp;
                t = i - 1;
                swapTimes++;
            }
        }
        left = t +1;

        //然後反向冒泡
        for (i = left; i         {
            circuTimes++;
            if (arr[i] > arr[i+1])
            {
                temp = arr[i+1];
                arr[i+1] = arr[i];
                arr[i] = temp;
                t = i + 1;
                swapTimes++;
            }
        }
        right = t - 1;
    } while(left
    end = clock();
    sort_perform.CircuTimes = circuTimes;
    sort_perform.MilliSeconds = end - start;
    sort_perform.SwapTimes = swapTimes;
    return sort_perform;
}

---------------------------------------------------------------------------------------------------------------------------------------------------------

經過測試可以發現這三種冒泡方式的效能資料如下,其中引用的資料都是基於原生,當然有些是不用測試也能猜到的,其中還有點比較有趣的地方:

1.正向冒泡和反向冒泡的效能是一樣的,這一點我想不用測試也可以瞭解。

2.雙向冒泡的效能要比前兩種好一些,但是這種好處要在資料量比較大的時候才明顯(5000個以上),在執行時間上可以比前兩種快大概1/4,但是它的這種快並不想我在網上查到的資料所說的交換次數較少。而恰恰相反,交換次數與前兩種一樣,但是迴圈次數會比前兩種冒泡減少1/3左右,時間就是從迴圈次數減少這裡獲得的。

3.雙向冒泡一個比較有趣的地方是,當資料趨於有序時,它的效率也越來越高。2中的結論都是基於亂序(random)的數組測試得出的結論。當數組越來越有序時,它的迴圈次數較快地減少,所以效率也越來越高。但是當數組絕對有序時,它的迴圈次數是前兩種的2倍!交換次數都是0。我測試過,當數組中只有一個元素無序時,它可以將迴圈次數節省99%以上(交換次數不變)!從而可以幾乎100%的節省時間!但是一旦絕對有序,它的迴圈次數就上升到兩倍!彷彿是物極必反,o(∩_∩)o...哈哈!

文章參考連結:http://www.zxbc.cn/html/20070425/7523.html

可以到這裡下載本文的所有代碼,包含效能測試部分(BubbleSort.cpp):http://download.csdn.net/source/590585

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.