簡單理解桶排序

  桶排序,利用編號分組存儲數字,再利用編號合併分組的一種算法排序。javascript

  舉個易於理解的例子:css

  一組數字,9,3,4,0,2,8,5,1,7,6,11,10,18,15,17,12,16,13,19,14html

  咱們把這組數字分組編號成10個桶裝起來,但怎麼編號分組呢?java

  這裏咱們利用數字範圍來對數字進行分桶。首先,最大數減去最小數,獲取這組數字的取值範圍,而後,咱們讓這個取值範圍除以桶數,獲取一個桶的取值範圍,既然知道一個桶的取值範圍,那麼,經過對比每一個數字佔用多少個桶,咱們就能夠獲取這個數字所對應的桶的編號了。(換一句話說,就是每一個數字佔用多少個取值範圍,這裏的桶其實就是數字的取值範圍的具體化東西)算法

  利用上面的例子作解釋:數組

  上面的最大值是19,最小值是0,因此這組數的取值範圍是:  19-0=19。ui

  咱們要用10個桶來分裝這組數字,則一個桶的取值範圍是:  19 / 10 = 1.9。spa

  因此,一個桶的取值範圍就是:  1.9。code

  知道了這些以後,咱們怎麼知道每一個數字所對應的桶的編號呢?xml

  咱們讓每一個數字減去最小值再除以一個桶的取值範圍就能夠得到這個數字所對應的桶編號了,爲何這麼說呢?由於咱們就是利用數值範圍來分桶的,因此理所固然的也是獲取每一個數字的取值範圍來分桶的編號,而最小值就是咱們的取值標準,固然是要每一個數字都減去它才能準確的獲取每一個數的取值範圍了。

  根據上面的解釋,那麼,第一個數字的桶編號就是:  (9-0) / 1.9 = 4.7368·······

  固然爲了確保編號爲整數,咱們必須給編號取整,這裏咱們是向上取整,因此第一個數:9的桶編號就是5啦。

  其餘的數字獲取桶編號都是一樣的原理,這裏就再也不重複敘述了。

  下面是js程序的實現:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
    <title>桶排序</title>
    <meta name="keywords" content="關鍵字列表" />
    <meta name="description" content="網頁描述" />
    <link rel="stylesheet" type="text/css" href="" />
    <style type="text/css"></style>
    <script type="text/javascript">
    //桶排序,參數數組,桶的個數,這裏用數組模擬桶
    var cask=function (arr,caskCount){
        //不是數組,返回false
        if(toString.call(arr) != '[object Array]'){
            return false;
        }
        //獲取數組的長度
        var len = arr.length;
        if(len <=1){
            return arr;//長度小於等於1不用排序
        }
        var list   = [],//裝桶的桶,用它來控制存儲桶的編號
            result = [],//返回的結果
            max    = arr[0],
            min    = arr[0];
        //默認桶的個數爲10
        var    caskCount = parseInt(caskCount) > 0 ? parseInt(caskCount) : 10;
        //獲取數組的最大值和最小值
        for(var i=1;i<len-1;i++){
             max = arr[i] <= max ? max : arr[i] ; 
             min = arr[i] >= min ? min : arr[i] ; 
        }
        //分紅caskCount個桶,桶所佔用的範圍
        var range = (max - min) / caskCount;
        for(var i=0;i<len;i++){
            //桶的數值減去最小數 min 獲取的是桶佔用的範圍,再除以一個桶的範圍,就是獲取對應的桶編號
            var index = Math.floor((arr[i] - min) / range);
            //桶裏是否有值,有值則進行排序
            if(list[index]){//用數組模擬桶
                //獲取桶最後一個值的下標 
                var k=list[index].length - 1;
                //桶最後的值大於要插進來的值,因此要把這個值插到桶的前面去,但不知道這個值要插入到前面的哪一個位置,因此,就只能對比排序了
                    //對桶進行排序
                    while(k >=0 && list[index][k] > arr[i]){
                        //桶前面的數字放到後面去
                        list[index][k+1] = list[index][k];//第一個k+1爲新增的桶
                        //小的提早一個位置
                        //list[index][k] = arr[i];
                        k--;
                    }
                //不用排序的,直接加在桶的最後面
                list[index][k+1] = arr[i];
            }else{
            //沒有值則生成桶,並把值放到對應的桶中
                list[index]=[];
                list[index][0]=arr[i];
            }
        }
        //合併桶
        var n=0;
        while(n <= caskCount){
            if(list[n]){
                result = result.concat(list[n]);
            }
            n++;
        }
        return result;
    }
    var arr=[8,39,400,500,3,4,20,44,440];
    alert(cask(arr,10));
    //alert(parseInt(-1) ? parseInt(-1) : 1);
    </script>
</head>
<body>

</body>
</html>
相關文章
相關標籤/搜索