它一種與其餘排序算法徹底不一樣的排序方法,其餘的排序算法都是經過關鍵字之間的比較和移動來完成的,而它是採用一種多關鍵字的思想。算法
多關鍵字的思想:給定一組數據,我能夠先按個位的大小對全部數進行排序,而後再按十位進行排序,一直到最高位,這樣就可使整組數據變得有效,這樣從最低位開始的方法稱爲最低位優先數組
通過一次放置和回收,獲得的序列已經按個位有序了,接下來按照次低位再次進行放置和回收。分佈式
由此能夠看出,若是一組序列中最大的數爲兩位數,則須要兩次的分配和收集,整個分配收集的次數與最大數的位數有關性能
基數排序須要兩個輔助空間,一個是0~9號桶,另外一個是計算定位的數組,定位數組是幹什麼的呢?就是記錄每一個桶中的數據待會要放回原數組的哪一個位置。大數據
def radixSort(number: Array[Int], d: Int): Unit = { //d表示最大的數有多少位 var k = 0 var n, m = 1 //控制鍵值排序依據在哪一位 val temp = Array.ofDim[Int](10, number.length) //數組的第一維表示可能的餘數0-9 val order = new Array[Int](10) //數組orderp[i]用來表示該位是i的數的個數 while (m <= d) { for (i <- number.indices) { val lsd = (number(i) / n) % 10 temp(lsd)(order(lsd)) = number(i) order(lsd) += 1 } var i = 0 while (i < 10) { if (order(i) != 0) { var j = 0 while (j < order(i)) { number(k) = temp(i)(j) k += 1 j += 1 } } order(i) = 0 i += 1 } n *= 10 k = 0 m += 1 } }
基數排序的時間複雜度能夠理解爲O(d*n),d爲序列中最大的位數,適用於n值很大,可是關鍵字較小的序列。scala
桶排序將[0,1)區間劃分爲n個相同的大小的子區間,這些子區間被稱爲桶。而後將n個輸入元素分別放入各自的桶中。由於輸入時均勻獨立的,因此通常不會有不少數同時落在一個桶中的狀況。這樣,咱們想對各個桶中的數據進行排序,而後遍歷每一個桶,按照次序把各個桶中的元素列出來便可blog
1》. 桶排序的時間複雜度一般是O(N+N*logM),其中,N表示桶的個數,M表示桶內元素的個數(這裏,M取的是一個大概的平均數,這也說明,爲什麼桶內的元素儘可能不要出現有的不少,有的不多這種分佈不均的事情,分佈不均的話,算法的性能優點就不能最大發揮)。排序
2》. 桶排序是穩定的(是能夠作到平衡排序的)。內存
3》. 桶排序,在內存方面消耗是比較大的,能夠說其時間性能優點是由犧牲空間換來的。input
桶排序,在大數據量的狀況下排序,比快速排序還要快。若待排序的數據元素個數比較少,桶排序的優點就不是那麼明顯了,由於桶排序就是基於分而治之的策略,能夠將數據進行分佈式排序,充分發揮並行計算的優點。
1》.找出待排序數組中的最大值max、最小值min
2》.咱們使用 動態數組ArrayList 做爲桶,桶裏放的元素也用 ArrayList 存儲。桶的數量爲(max-min)/arr.length+1
3》.遍歷數組 arr,計算每一個元素 arr[i] 放的桶
4》.每一個桶各自排序
5》.遍歷桶數組,把排序好的元素放進輸出數組
def bucketsort(inputData: ArrayBuffer[Int], max: Int): ArrayBuffer[Int] = { var buckets = new Array[Int](max) for (i <- inputData.indices) //計數 buckets(inputData(i)) = buckets(inputData(i)) + 1 var j = 0 for (i <- 0 until max) while (buckets(i) > 0) { inputData(j) = i j = j + 1 buckets(i) = buckets(i) - 1 } buckets = null inputData }
計數排序是桶排序的一種特殊狀況,能夠把計數排序當成每一個桶裏只有一個元素的狀況,它是一個非基於比較的排序算法,它的優點在於在對必定範圍內的整數排序時,它的複雜度爲Ο(n+k)(其中k是整數的範圍),快於任何比較排序算法。
對於一個輸入數組中的一個元素x,若是這個數組中比x小的元素有n個,那麼咱們就能夠直接把x放到(n+1)的位置上。這就是計數排序的基本思想,相似於哈希表中的直接定址法,在給定的一組序列中,先找出該序列中的最大值和最小值,從而肯定須要開闢多大的輔助空間,每個數在對應的輔助空間中都有惟一的下標。
基於這個思想,計數排序的一個主要問題就是如何統計數組中元素的個數。再加上輸入數組中的元素都是0-k區間的一個整數這個條件,那麼就能夠經過另一個數組的地址表示輸入元素的值,數組的值表示元素個數的方法來進行統計。
下面給出統計數組元素都是0-k區間的整數的數組中各個元素個數的方法。
計數排序是一種以空間換時間的排序算法,而且只適用於待排序列中全部的數較爲集中時,好比一組序列中的數據爲0 1 2 3 4 999;就得開闢1000個輔助空間。
時間複雜度
計數排序的時間度理論爲O(n+k),其中k爲序列中數的範圍。
不過當O(k)>O(n*log(n))的時候其效率反而不如基於比較的排序(基於比較的排序的時間複雜度在理論上的下限是O(n*log(n)), 如歸併排序,堆排序)
def Countingsort(inputData: ArrayBuffer[Int], k: Int): Array[Int] = { //k表示有所輸入數字都介於0到k之間 val temp = new Array[Int](k) // 臨時存儲區 val outdata = new Array[Int](inputData.length) val len = temp.length for (i <- 0 until len) { // 初始化 temp(i) = 0 } for (i <- inputData.indices) { temp(inputData(i)) = temp(inputData(i)) + 1 } for (i <- 1 until len) { temp(i) = temp(i) + temp(i - 1) } // 把輸入數組中的元素放在輸出數組中對應的位置上 var n = inputData.length - 1 while (n >= 0) { // 從後往前遍歷 outdata(temp(inputData(n)) - 1) = inputData(n) temp(inputData(n)) = temp(inputData(n)) - 1 n = n - 1 } outdata }