三大線性排序之桶排序

一.概念引入html

        有做者把計數排序也稱爲桶排序(各個桶中元素的排序採用計數排序),獲得數組C後直接從前日後遍歷,輸出數組值次數組下標,爲0就不輸出(或者存入原數組,不穩定),不過筆者認爲這種說法不嚴謹(一個很明顯的問題是輸出會是雙重for循環,不過也有那個意思,叫鴿巢排序也何嘗不可),由於桶排序要求輸入數據在[0,1)範圍內(計數排序要求整數;實際上要麼全是整數,要麼小數,便於劃分桶),先把區間[0,1)劃分紅n個相同大小的子區間,稱爲桶,而後將n個輸入數分佈到各個桶中去。由於輸入數均勻且獨立分佈在[0,1)上,因此,通常不會有不少數落在一個桶中的狀況。爲了獲得結果,先對各個桶中的數進行排序,而後按次序把各桶中的元素列出來。java

        附上鴿巢排序核心源代碼:git

public void pigeonSort(int[] array, int max) {  
    int[] c = new int[max];//max是array數組中的最大值
    for(int i=0; i<array.length; i++)   
        c[array[i]]++;  
    //c數組只是統計元素出現次數
    int k = 0;
    for(int i=0; i<max; i++)   
        for(int j=1; j<=c[i]; j++)  
            array[k++] = i;  
}

二.算法描述面試

        例如要對大小爲[1..1000]範圍內的n個整數A[1..n]排序,能夠把桶設爲大小爲10的範圍,具體而言,設集合B[1]存儲[1..10]的整數,集合B[2]存儲(10..20]的整數,……集合B[i]存儲((i-1)*10, i*10]的整數,i = 1,2,..100。總共有100個桶。而後對A[1..n]從頭至尾掃描一遍,把每一個A[i]放入對應的桶B[j]中。 而後再對這100個桶中每一個桶裏的數字排序,這時可用冒泡,選擇,乃至快排,通常來講任何排序法均可以。最後依次輸出每一個桶裏面的數字,且每一個桶中的數字從小到大輸出,這樣就獲得全部數字排好序的一個序列了。 算法

        下圖表示出了桶排序做用於有10個數的輸入數組上的操做過程。數組

三.算法的Java實現dom

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

public class BucketSort {

    public static void bucketSort(double array[]) {
        int length = array.length;
        ArrayList arrList[] = new ArrayList[length];
        /*
         *  每一個桶是一個list,存放落在此桶上的元素
         *  上次的基數排序我採用的是計數排序實現的,其實也能夠用下面的方法,有興趣的讀者不妨一試(我認爲太複雜)
         *  不過效率估計不高(採用了動態數組)
         */
        //劃分桶並填元素
        for (int i = 0; i < length; i++) {
            //0.7到0.79放在第8個桶裏,編號7;第一個桶放0到0.09
            int temp = (int) Math.floor(10 * array[i]);
            if (null == arrList[temp])
                arrList[temp] = new ArrayList();
            arrList[temp].add(array[i]);
        }
        // 對每一個桶中的數進行插入排序
        for (int i = 0; i < length; i++) {
            if (null != arrList[i]) {
                //此處排序方法不定,不過越快越好,除了三大線性排序外,都沒有Collections
                //和Arrays裏的sort好,由於這是調優後的快拍
                //Arrays裏也有,在基數排序裏用過copyOf和fill方法
                Collections.sort(arrList[i]);
            }
                
        }
        //輸出相似鴿巢排序
        int count = 0;
        for (int i = 0; i < length; i++) {
            if (null != arrList[i]) {
                Iterator iter = arrList[i].iterator();
                while (iter.hasNext()) {
                    Double d = (Double) iter.next();
                    array[count] = d;
                    count++;
                }
            }
        }
    }

    /*
     * 每一個元素知足0<=array[i]<1,貌似還要長度相同,
     * 如果相同小數位(digit),則能夠把小數搞爲整數,最後再除以10^digit
     *  能夠Random.nextInt(101)/100
     */
    public static void main(String[] args) {
        double array[] = { 0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12,
                0.23, 0.68 };
        bucketSort(array);
        for (int i = 0; i < array.length; i++)
            System.out.print(array[i] + " ");
        System.out.println();
    }
}

四.算法應用spa

        在面試的海量數據處理題目中,如對天天數以億計的數據進行排序,直接排序即便採用nlgn的算法,依然是一件很恐怖的事情,內存也沒法容納如此多的數據,這時桶排序就能夠有效地下降數據的數量級,再對下降了數量級的數據進行排序,能夠獲得比較良好的效果。另外也有說桶排序對元組排序,我的認爲仍是基數排序處理元組比較好,畢竟自己就是多關鍵字排序,只須要把比較單個數字(有興趣的參看個人這一篇《基於計數排序的基數排序》http://www.cnblogs.com/hxsyl/p/3210647.html)換成比較單個元組元素就好。              code

相關文章
相關標籤/搜索