排序算法(九):桶排序

桶排序是將待排序集合中處于同一個值域的元素存入同一個桶中朗兵,也就是根據(jù)元素值特性將集合拆分為多個區(qū)域,則拆分后形成的多個桶柿隙,從值域上看是處于有序狀態(tài)的叶洞。對每個桶中元素進(jìn)行排序,則所有桶中元素構(gòu)成的集合是已排序的禀崖。

快速排序是將集合拆分為兩個值域衩辟,這里稱為兩個桶,再分別對兩個桶進(jìn)行排序波附,最終完成排序艺晴。桶排序則是將集合拆分為多個桶,對每個桶進(jìn)行排序掸屡,則完成排序過程封寞。兩者不同之處在于,快排是在集合本身上進(jìn)行排序仅财,屬于原地排序方式狈究,且對每個桶的排序方式也是快排。桶排序則是提供了額外的操作空間盏求,在額外空間上對桶進(jìn)行排序谦炒,避免了構(gòu)成桶過程的元素比較和交換操作,同時可以自主選擇恰當(dāng)?shù)呐判蛩惴▽ν斑M(jìn)行排序风喇。

當(dāng)然桶排序更是對計數(shù)排序的改進(jìn)宁改,計數(shù)排序申請的額外空間跨度從最小元素值到最大元素值,若待排序集合中元素不是依次遞增的魂莫,則必然有空間浪費情況还蹲。桶排序則是弱化了這種浪費情況,將最小值到最大值之間的每一個位置申請空間耙考,更新為最小值到最大值之間每一個固定區(qū)域申請空間谜喊,盡量減少了元素值大小不連續(xù)情況下的空間浪費情況。

桶排序過程中存在兩個關(guān)鍵環(huán)節(jié):
  • 元素值域的劃分倦始,也就是元素到桶的映射規(guī)則斗遏。映射規(guī)則需要根據(jù)待排序集合的元素分布特性進(jìn)行選擇,若規(guī)則設(shè)計的過于模糊鞋邑、寬泛诵次,則可能導(dǎo)致待排序集合中所有元素全部映射到一個桶上账蓉,則桶排序向比較性質(zhì)排序算法演變。若映射規(guī)則設(shè)計的過于具體逾一、嚴(yán)苛铸本,則可能導(dǎo)致待排序集合中每一個元素值映射到一個桶上,則桶排序向計數(shù)排序方式演化遵堵。
  • 排序算法的選擇箱玷,從待排序集合中元素映射到各個桶上的過程,并不存在元素的比較和交換操作陌宿,在對各個桶中元素進(jìn)行排序時锡足,可以自主選擇合適的排序算法,桶排序算法的復(fù)雜度和穩(wěn)定性壳坪,都根據(jù)選擇的排序算法不同而不同舶得。

算法過程

  1. 根據(jù)待排序集合中最大元素和最小元素的差值范圍和映射規(guī)則,確定申請的桶個數(shù)弥虐;
  2. 遍歷待排序集合扩灯,將每一個元素移動到對應(yīng)的桶中媚赖;
  3. 對每一個桶中元素進(jìn)行排序霜瘪,并移動到已排序集合中。

步驟 3 中提到的已排序集合惧磺,和步驟 1颖对、2 中的待排序集合是同一個集合。與計數(shù)排序不同磨隘,桶排序的步驟 2 完成之后缤底,所有元素都處于桶中,并且對桶中元素排序后番捂,移動元素過程中不再依賴原始集合个唧,所以可以將桶中元素移動回原始集合即可。

演示示例

待排序集合為:[-7, 51, 3, 121, -3, 32, 21, 43, 4, 25, 56, 77, 16, 22, 87, 56, -10, 68, 99, 70]
映射規(guī)則為:f(x)=\frac x{10}-c设预,其中常量位:c=\frac {min}{10}徙歼,即以間隔大小 10 來區(qū)分不同值域
排序算法為:堆排序,根據(jù)堆排序特性可知鳖枕,K 個元素的集合魄梯,時間復(fù)雜度為:Klog_2K,算法不保持穩(wěn)定性

step 1:

遍歷集合可得宾符,最大值為:max=121酿秸,最小值為:min=-10,待申請桶的個數(shù)為:\frac {max}{10}-\frac {min}{10}+1=12-(-1)+1=14

step 2:

遍歷待排序集合魏烫,依次添加各元素到對應(yīng)的桶中辣苏。

桶下標(biāo) 桶中元素
0 -7, -3, -10
1 3, 4
2 16
3 21, 25, 22
4 32
5 43
6 51, 56, 56
7 68
8 77, 70
9 87
10 99
11
12
13 121

step 3:

對每一個桶中元素進(jìn)行排序肝箱,并移動回原始集合中,即完成排序過程考润。

算法示例

def bucketSort(arr):
    maximum, minimum = max(arr), min(arr)
    bucketArr = [[] for i in range(maximum // 10 - minimum // 10 + 1)]  # set the map rule and apply for space
    for i in arr:  # map every element in array to the corresponding bucket
        index = i // 10 - minimum // 10
        bucketArr[index].append(i)
    arr.clear()
    for i in bucketArr:
        heapSort(i)   # sort the elements in every bucket
        arr.extend(i)  # move the sorted elements in bucket to array

第一個循環(huán)作用為將待排序集合中元素移動到對應(yīng)的桶中狭园,復(fù)雜度為 O(N);第二個循環(huán)的作用為對每個桶中元素進(jìn)行排序糊治,并移動回初始集合中唱矛,若桶個數(shù)為 M,平均每個桶中元素個數(shù)為 \frac NM井辜,則復(fù)雜度為 O(M*\frac NMlog_2{\frac NM}+N)=O(N+N(log_2N-log_2M))绎谦。當(dāng) M==N 時,即桶排序向計數(shù)排序方式演化粥脚,則堆排序不發(fā)揮作用窃肠,復(fù)雜度為 O(N),只需要將元素移動回初始集合即可刷允。當(dāng) M==1 時冤留,即桶排序向比較性質(zhì)排序算法演化,對集合進(jìn)行堆排序树灶,并將元素移動回初始集合纤怒,復(fù)雜度為 O(N+Nlog_2N)

算法分析

由算法過程可知天通,桶排序的時間復(fù)雜度為 O(N+N(log_2N-log_2M))泊窘,其中 M 表示桶的個數(shù)。由于需要申請額外的空間來保存元素像寒,并申請額外的數(shù)組來存儲每個桶烘豹,所以空間復(fù)雜度為 O(N+M)。算法的穩(wěn)定性取決于對桶中元素排序時選擇的排序算法诺祸。由桶排序的過程可知携悯,當(dāng)待排序集合中存在元素值相差較大時,對映射規(guī)則的選擇是一個挑戰(zhàn)筷笨,可能導(dǎo)致元素集中分布在某一個桶中或者絕大多數(shù)桶是空桶的現(xiàn)象憔鬼,對算法的時間復(fù)雜度或空間復(fù)雜度有較大影響,所以同計數(shù)排序一樣奥秆,桶排序適用于元素值分布較為集中的序列逊彭。

github 鏈接:桶排序

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市构订,隨后出現(xiàn)的幾起案子侮叮,更是在濱河造成了極大的恐慌,老刑警劉巖悼瘾,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件囊榜,死亡現(xiàn)場離奇詭異审胸,居然都是意外死亡,警方通過查閱死者的電腦和手機卸勺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門砂沛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人曙求,你說我怎么就攤上這事碍庵。” “怎么了悟狱?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵静浴,是天一觀的道長。 經(jīng)常有香客問我挤渐,道長苹享,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任浴麻,我火速辦了婚禮得问,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘软免。我一直安慰自己宫纬,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布或杠。 她就那樣靜靜地躺著哪怔,像睡著了一般宣蔚。 火紅的嫁衣襯著肌膚如雪向抢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天胚委,我揣著相機與錄音挟鸠,去河邊找鬼。 笑死亩冬,一個胖子當(dāng)著我的面吹牛艘希,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播硅急,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼覆享,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了营袜?” 一聲冷哼從身側(cè)響起撒顿,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荚板,沒想到半個月后凤壁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吩屹,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年拧抖,在試婚紗的時候發(fā)現(xiàn)自己被綠了煤搜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡唧席,死狀恐怖擦盾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淌哟,我是刑警寧澤厌衙,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站绞绒,受9級特大地震影響婶希,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蓬衡,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一喻杈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧狰晚,春花似錦筒饰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至秒咐,卻和暖如春谬晕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背携取。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工攒钳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雷滋。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓不撑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親晤斩。 傳聞我的和親對象是個殘疾皇子焕檬,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354