/* * -桶排序* * -
/*
桶排序假設輸入元素均勻獨立地分布在區間[0,1],即0
*/
//插入排序算法
insert_sort =函數(數組){
for(right = 2;#array ) {
var top = array[right];
//將數組[right]插入排序後的序列數組[1....右-1]
var left = right-1;
while( left和array[left]>頂部){
數組[left+1] =數組[left];
左-;
}
array[left+1]= top;
}
返回數組;
}
//桶排序算法
bucket_sort = function( array ){
var n = # array
var bucket ={}
for(I = 0;n;1){
Bucket[i] = {} //創建壹個存儲桶。
}
var桶_指數
for(I = 1;n;1){
bucket _ index = math . floor(n * array[I]);
table . push(bucket[bucket _ index],array[I]);//放在桶裏
}
for(I = 1;n;1){
insert _ sort(bucket[I]);//插入並排序每個存儲桶。
}
返回table . concat(table . unpack(bucket))
}
io.print( -)
Io.print(桶排序)
io.print( -)
array = { };
//桶排序假設輸入是隨機過程生成的小數。
math .隨機化()
for(I = 1;20;1){
table.push( array,math.random())
}
//排序
array = bucket_sort(數組)
//輸出結果
for(I = 1;#數組;1){
io.print( array[i])
}
執行(暫停)//按任意鍵繼續。
io . close();//全國高考考生關閉控制臺壹年人數500萬,分數標準化,最低100分,最高900分,無小數。需要對500萬個元素的數組進行排序。
分析:如果基於比較的高級排序對500W數據進行排序,平均比較次數為O(5000000 * log 5000000)≈1.112億。但是我們發現這些數據有特殊的條件:100 =
方法:創建801(900-100)個桶。用f(分數)=score-100把每個考生的分數扔進桶裏。這個過程從頭到尾遍歷數據只需要500W次。然後按照桶號的大小依次輸出桶中的值,就可以得到壹個有序的序列。而且和* *人可以輕松獲得100積分,和* * *人可以獲得501積分。
事實上,桶排序對數據條件有特殊要求。如果上面的分數不是從100-900,而是從0-2億,顯然不可能分配到2億桶。因此,桶排序有其局限性,適合元素值集合不大的情況。壹個文件有10G個整數,排列順序不對。要求求中位數。內存限制為2G。把想法寫出來就行了(內存限制是2G,也就是說妳可以用2G空間運行程序,不考慮本機其他軟件的內存占用。)關於中位數:數據排序後位於中間的值。即數據分為兩部分,壹部分大於這個值,另壹部分小於這個值。中位數的位置:樣本數為奇數時,中位數=(N+1)/2;當樣本數為偶數時,中位數是N/2和1+N/2的平均值(那麽中位數10G是第5個最大數和第5個最大數+1的平均值)。
分析:既然是求中位數,那就是單純的排序的思路。那麽基於字節的桶排序是壹種可行的方法。
思想:以整數的每1字節為壹個關鍵字,也就是說壹個整數可以分解成四個鍵,最高位的鍵越大,整數越大。如果高位鍵相同,則比較第二個高位鍵的鍵。整個比較過程類似於字符串的字典順序。
第壹步:每2G將10G的整數讀入內存壹次,然後壹次性遍歷這536,870,912,即(1024 * 1024 * 1024)* 2/4個數據。每個數據的位操作>:& gt取出最高的8位(31-24)。這個8bits(0-255)最多代表256個桶,妳可以根據8bit的值來確定要扔到哪個桶裏。最後將每個桶寫入壹個磁盤文件,統計內存中每個桶的數據個數[256]。
成本:(1) 10G數據依次讀入內存的IO成本(這是無法避免的,CPU無法直接在磁盤上操作)。(2)在內存中遍歷536,870,965,438+02個數據,是O(n)的線性時間復雜度。(3)將256個桶寫回256個磁盤文件空間的成本是額外的,即傳輸10G數據需要兩倍的時間。
第二步:根據內存中256個桶中的數字NUM[256],計算出中位數在哪個桶中。很明顯,2684354560的中位數就是1,342177280。假設加上前127桶的數據量,發現小於1,342,177,280。如果加上128桶的數據量,大於1,342,177,280。說明,中位數必須在磁盤的第128桶。而在這個桶的1,342,177,280-n (0-127)位上。N(0-127)表示前127個存儲桶的數據總和。然後將128文件中的整數讀入內存。(如果數據大致均勻分布,每個文件的大小估計在10G/256=40M左右,當然不壹定,但超過2G的可能性很小)。請註意,在異常情況下,文件編號。要讀取的128仍然大於2G,所以整個讀取仍然可以按照第壹步批量讀取。
開銷:(1)循環計算255個桶中的數據累加,需要O(M)的開銷,其中M
第三步:繼續按內存中壹個桶的整數的第二高8位對桶進行排序(它們的最高8位相同)(23-16)。流程同第壹步,256桶。
第四步:繼續進行,直到最低字節(7-0bit)的桶排序完成。我相信這個時候,用壹次內存中的fast rank就夠了。
整個過程的時間復雜度在O(n)的線性水平上(沒有任何循環嵌套)。但是主要時間花在了第壹步的第二次內存-磁盤數據交換上,也就是10G數據分255個文件寫回磁盤。壹般來說,如果壹個有中值的文件在第二步之後內存中可以容納,就可以直接快速排列(修訂者註:我覺得不寫回磁盤繼續桶排序會更有效率?)。