1. 程式人生 > >看圖輕鬆理解桶排序

看圖輕鬆理解桶排序

前言

推出一個新系列,《看圖輕鬆理解資料結構和演算法》,主要使用圖片來描述常見的資料結構和演算法,輕鬆閱讀並理解掌握。本系列包括各種堆、各種佇列、各種列表、各種樹、各種圖、各種排序等等幾十篇的樣子。

桶排序

桶排序即Bucket Sort,也稱箱排序。其基本思想是將待排序陣列分配到若干個桶內,然後每個桶內再各自進行排序,桶內的排序可以使用不同的演算法,比如插入排序或快速排序,屬於分治法。每個桶執行完排序後,最後依次將每個桶內的有序序列拿出來,即得到完整的排序結果。

時間複雜度

設有n個元素,進行桶排序的時間複雜度分為兩個部分:

  1. 計算每個元素分配到哪個桶,時間複雜度是O(N)。
  2. 假如在桶內使用快速排序,則時間複雜度為\sum_{i=0}^{m}{O(n_i*logn_i)},其中n_i為第i個桶的資料量。

所以桶排序總的時間複雜度為兩者之和。

排序要點

簡單來看,桶排序的分治涉及到三部分:分、治、合。分,即將序列分成m個小序列;治,即對每個桶內的元素進行排序;合,即將每個桶合併到一起。

設待排序陣列為a[0],a[1],...a[n-1],並且假設資料符合均勻分佈,桶排序步驟為:

  1. 根據序列大小範圍劃分m個大小相同的區間,每個區間即是一個桶。
  2. 將待排序的n個元素分發到對應區間的桶中,即是分操作。
  3. 對每個桶包含的元素進行排序,可以使用快速排序或其他排序,即是治操作。
  4. 每個桶都是有序序列,按桶順序依次取出每個桶的元素,得到最終完整的有序陣列,即是合操作。

桶的區間

既然是分開治理,那當然是每個桶都平均才更高效,所以最理想的狀態是每個桶都分配到相同或很接近的資料量。可以設想在分配不均的情況下,桶中元素少的早已處理完而元素多的還得處理很長一段時間,導致效率低下。

但待排序資料並非總是均勻分佈的,可能是正態分佈或邏輯斯蒂分佈之類的,此時為了能使每個桶的資料量均勻,桶的區間可以根據概率密度函式來確定。

排序過程

假設我們有如下10個元素,分別為4, 7, 9, 13, 18, 1, 19, 11, 6, 15。另外,假設我們的桶使用有序連結串列結構,現在進行桶排序。

首先先定義桶的數量及區間,因為待排序陣列的最大元素與最小元素分別為19和1,那麼總的範圍區間可定義為[0,19],假設用4個桶,則桶的區間分別為[0,4][5,9][10,14][15,19]

image

開始將陣列元素逐一分配到對應的桶中,第一個元素是4,分配到0號桶內。

image

第二個元素是7,分配到1號桶。

image

第三個元素是9,分配到1號桶,為了保證桶的有序連結串列,將9與7進行比較,

image

由於9大於7,於是9作為7的後繼節點。

image

第四個元素是13,分配到2號桶。

image

第五個元素是18,分配到3號桶。

image

第六個元素是1,為保證桶的有序連結串列,1作為4的前驅結點。

image

第七個元素是19,為保證桶的有序連結串列,19作為18的後繼結點。

image

類似的,將剩下的三個元素分配到對應的桶內,同時保證桶內為有序連結串列,最終結果如下。

image

現在每個桶都是一個有序序列,最後要執行合併操作,即按桶順序依次取出每個桶的元素,最終完成整個序列的排序。

先取出0號桶的所有元素,分別為1、4。

image

接著取出1號桶的所有元素,分別為6、7、9。

image

繼續取出2號桶的所有元素,分別為11、13。

image

最後取出3號桶的所有元素,分別為15、18、19。

image

至此完成整個排序工作。

-------------推薦閱讀------------

我的開源專案彙總(機器&深度學習、NLP、網路IO、AIML、mysql協議、chatbot)

為什麼寫《Tomcat核心設計剖析》

我的2017文章彙總——機器學習篇

我的2017文章彙總——Java及中介軟體

我的2017文章彙總——深度學習篇

我的2017文章彙總——JDK原始碼篇

我的2017文章彙總——自然語言處理篇

我的2017文章彙總——Java併發篇


跟我交流,向我提問:

歡迎關注: