有趣的桶排序

程序員的核心技能之一就是算法,談到算法,似乎都是從排序開(kāi)始。對(duì)一組已知范圍的數(shù)據(jù)進(jìn)行排序,最快的算法是什么呢?快速排序?希爾排序?非也,非也~是本文的主角“桶排序”!
  來(lái)看一個(gè)實(shí)際例子吧:已知一組范圍在0~10的數(shù)據(jù)(如:9,5,2,7,7),你有沒(méi)有什么好方法編寫(xiě)一段程序,將數(shù)據(jù)從大到小輸出呢?
  看到這樣的題目,相信很多人第一反應(yīng)跟我一樣,就是將這些數(shù)據(jù)進(jìn)行比較,然后進(jìn)行位置的交換,最終實(shí)現(xiàn)排序。可桶排序徹底顛覆了這種想法——第一次看到桶排序時(shí),確實(shí)被驚艷到了——還有這種操作?!原來(lái)排序不一定非得老老實(shí)實(shí)對(duì)原有數(shù)據(jù)進(jìn)行位置調(diào)整!
  好了,回到我們的題目。我們只需要借助一個(gè)一維數(shù)組就可以解決問(wèn)題。首先,我們申請(qǐng)一個(gè)長(zhǎng)度為11的數(shù)組int a[11],因?yàn)槲覀兊臄?shù)據(jù)范圍是0~10,而int a[11]的元素正好是a[0]~a[10]。開(kāi)始的時(shí)候,我們將所有元素都初始化為0,表示這些數(shù)都未出現(xiàn)過(guò)。例如a[0]等于0,就表示待排序數(shù)據(jù)還未出現(xiàn)過(guò)0;同理,若a[9]等于1,則表示待排數(shù)據(jù)中9出現(xiàn)過(guò)1次。
  有了上面的說(shuō)明,那接下來(lái)就非常簡(jiǎn)單了,我們只需要遍歷待排數(shù)組,然后將每個(gè)數(shù)值對(duì)應(yīng)下標(biāo)的元素加1(比如第一個(gè)數(shù)是9,我們就將a[9]加1)。你會(huì)發(fā)現(xiàn),待排數(shù)組遍歷完之后,a[0]~a[10]中的數(shù)值,其實(shí)就是0~10出現(xiàn)的次數(shù),我們只需要按次數(shù)將下標(biāo)打印出來(lái)就實(shí)現(xiàn)排序了。代碼如下:

#include <stdio.h>
int main()
{
    int a[11],i,j,t;
    for(i=10; i>=0; i--)
    {
        a[i]=0;
    }

    for(i=1; i<=5; i++) //循環(huán)讀入5個(gè)待排數(shù)
    {
        scanf("%d",&t); //把每一個(gè)數(shù)讀到變量t中
        a[t]++; //進(jìn)行計(jì)數(shù)
    }

    for(i=10; i>=0; i--)
    {
        for(j=1; j<=a[i];j++)
        {
            printf("%d ",i);
        }
    }

    printf("\r\n"); 
    getchar();  
    return 0;
}

執(zhí)行該程序,我們可以隨意輸入5個(gè)0~10的數(shù)字,然后程序會(huì)將其按從大到小排序輸出,如下圖:

圖1

  接下來(lái)我們來(lái)看看時(shí)間復(fù)雜度。首先我們用了一個(gè)m次(m為桶的個(gè)數(shù))的循環(huán)把桶清空;然后再用一個(gè)n次(n為待排序數(shù)據(jù)的個(gè)數(shù))的循環(huán),設(shè)置的數(shù)據(jù)的顯示次數(shù);最后又進(jìn)行了m+n次循環(huán),把數(shù)據(jù)顯示出來(lái)。所以,整個(gè)排序算法一共執(zhí)行了m+n+m+n次。我們用大寫(xiě)字母O來(lái)表示時(shí)間復(fù)雜度,因此該算法的時(shí)間復(fù)雜度是O(m+n+m+n)即O(2*(m+n))。我們?cè)谡f(shuō)時(shí)間復(fù)雜度的時(shí)候可以忽略較小的常數(shù),最終桶排序的時(shí)間復(fù)雜度為O(m+n)。還有一點(diǎn),在表示時(shí)間復(fù)雜度的時(shí)候,n和m通常用大寫(xiě)字母即O(M+N),這是一個(gè)非??斓呐判蛩惴?。
  桶排序雖快,但其實(shí)它是用空間在換時(shí)間。如果需要排序的數(shù)范圍非常寬,那我們就需要申請(qǐng)非常多的“桶”來(lái)存儲(chǔ)每一個(gè)數(shù)出現(xiàn)的次數(shù)。即使依然只是需要對(duì)5個(gè)數(shù)進(jìn)行排序,這太浪費(fèi)空間了!所以在選擇使用哪種排序算法之前,還是需要根據(jù)實(shí)際情況,權(quán)衡好復(fù)雜度與空間的問(wèn)題。

參考書(shū)籍:《啊哈!算法》
說(shuō)明:本文所提到的是簡(jiǎn)化版的桶排序算法,真正的同排序算法要復(fù)雜些,有興趣的朋友可以自行搜索學(xué)習(xí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,697評(píng)論 19 139
  • 數(shù)據(jù)結(jié)構(gòu)與算法——計(jì)數(shù)排序、桶排序、基數(shù)排序 計(jì)數(shù)排序 計(jì)數(shù)排序有如下四個(gè)步驟。 首先會(huì)對(duì)每個(gè)輸入進(jìn)行頻率統(tǒng)計(jì),得...
    sunhaiyu閱讀 1,247評(píng)論 0 11
  • 某次二面時(shí),面試官問(wèn)起Js排序問(wèn)題,吾絞盡腦汁回答了幾種,深感算法有很大的問(wèn)題,所以總計(jì)一下! 排序算法說(shuō)明 (1...
    流浪的先知閱讀 1,255評(píng)論 0 4
  • 概述:排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    每天刷兩次牙閱讀 3,829評(píng)論 0 15
  • 一場(chǎng)放逐心靈的救贖 靜下心來(lái)認(rèn)認(rèn)真真地寫(xiě)份東西,還是很珍惜這種踏實(shí)安心的感覺(jué)。 《肖申克的救贖》(《TheShaw...
    Mon阿修閱讀 430評(píng)論 0 1

友情鏈接更多精彩內(nèi)容