PHP實現排序演算法----基數排序(Radix Sort)

來源:互聯網
上載者:User

基數排序在《大話資料結構》中並未講到,但是為了湊齊八大排序演算法,我自己通過網路學習了這個排序演算法,並給大家分享出來。 基本思想:

基數排序(radix sort)屬於“分配式排序”(distribution sort),又稱“桶子法”(bucket sort)或bin sort,顧名思義,它是透過索引值的部份資訊,將要排序的元素分配至某些“桶”中,藉以達到排序的作用,基數排序法是屬於穩定性的排序,其時間複雜度為O (nlog(r)m),其中r為所採取的基數,而m為堆數,在某些時候,基數排序法的效率高於其它的穩定性排序法。

其實這個思想我也沒法總結出來,下面通過例子來說明吧: 基本解法:

PS:在這裡我們介紹的基數排序我們採用 LSD(最低位優先),當然還有 MSD(最高位優先),大家自己去百度一下他們之間的異同吧。

假如現在我們有以下這麼一些數:

2 343 342 1 128 43 4249 814 687 654 3

我們使用基數排序將他們從小到大排序。

第一步、首先根據個位元的數值,在走訪數值(從前到後走訪,後面步驟相同)時將它們分配至編號0到9的桶子中:

0 : 1 : 12 : 2 342 3 : 343 43 34 : 814 6545 : 6 : 7 : 6878 : 1289 : 4249

第二步、接下來將這些桶子中的數值重新串接起來,成為以下的數列:

1 2 342 343 43 3 814 654 687 128 4249

第三步、根據十位元的數值,在走訪數值(從前到後走訪,後面步驟相同)時將它們分配至編號0到9的桶子中:

0 : 1 2 3 1 : 814 2 : 1283 : 4 : 342 343 43 42495 : 6546 : 7 : 8 : 6879 : 

第四步、接下來將這些桶子中的數值重新串接起來,成為以下的數列:

1 2 3 814 128 342 343 43 4249 654 687

第五步、根據百位元的數值,在走訪數值(從前到後走訪,後面步驟相同)時將它們分配至編號0到9的桶子中:

0 : 1 2 3 43 1 : 1282 : 42493 : 342 3434 : 5 : 6 : 654 6877 : 8 : 814 9 : 

第六步、接下來將這些桶子中的數值重新串接起來,成為以下的數列:

1 2 3 43 128 4249 342 343 654 687 814

。。。。。。後面的步驟大家應該都會走了吧。其實到了第六步的時候就剩 4249 沒有排好序了。

從上面的步驟來看,很多的步驟都是相同的,因此肯定是個迴圈了,我們只需要控制個位、十位、百位、、、、就好了。

還是看代碼吧。 演算法實現:

//交換函數function swap(array &$arr,$a,$b){    $temp = $arr[$a];    $arr[$a] = $arr[$b];    $arr[$b] = $temp;}//擷取數組中的最大數//就像上面的例子一樣,我們最終是否停止演算法不過就是看數組中的最大值:4249,它的位元就是迴圈的次數function getMax(array $arr){    $max = 0;    $length = count($arr);    for($i = 0;$i < $length;$i ++){        if($max < $arr[$i]){            $max = $arr[$i];        }    }    return $max;}//擷取最大數的位元,最大值的位元就是我們分配桶的次數function getLoopTimes($maxNum){    $count = 1;    $temp = floor($maxNum / 10);    while($temp != 0){        $count ++;        $temp = floor($temp / 10);    }    return $count;}/** * @param array $arr 待排序數組 * @param $loop 第幾次迴圈標識 * 該函數只是完成某一位(個位或十位)上的桶排序 */function R_Sort(array &$arr,$loop){    //桶數組,在強型別語言中,這個數組應該聲明為[10][count($arr)]    //第一維是 0-9 十個數    //第二維這樣定義是因為有可能待排序的數組中的所有數的某一位上的只是一樣的,這樣就全擠在一個桶裡面了    $tempArr = array();    $count = count($arr);    //初始化$tempArr數組    for($i = 0;$i < 10;$i ++){        $tempArr[$i] = array();    }    //求桶的index的除數    //如798個位桶index=(798/1)%10=8    //十位桶index=(798/10)%10=9    //百位桶index=(798/100)%10=7    //$tempNum為上式中的1、10、100    $tempNum = (int)pow(10, $loop - 1);    for($i = 0;$i < $count;$i ++){        //求出某位上的數字        $row_index = ($arr[$i] / $tempNum) % 10;        for($j = 0;$j < $count;$j ++){            if(@$tempArr[$row_index][$j] == NULL){                $tempArr[$row_index][$j] = $arr[$i];     //入桶                break;            }        }    }    //還原回原數組中    $k = 0;    for($i = 0;$i < 10;$i ++){        for($j = 0;$j < $count;$j ++){            if(@$tempArr[$i][$j] != NULL){                $arr[$k ++] = $tempArr[$i][$j];    //出桶                $tempArr[$i][$j] = NULL;   //避免下次迴圈的時候汙染資料            }        }    }}//最終調用的主函數function RadixSort(array &$arr){    $max = getMax($arr);    $loop = getLoopTimes($max);    //對每一位進行桶分配(1 表示個位,$loop 表示最高位)    for($i = 1;$i <= $loop;$i ++){        R_Sort($arr,$i);    }}

調用演算法:

$arr = array(2, 343, 342, 1, 128, 43, 4249, 814, 687, 654, 3);RadixSort($arr);var_dump($arr);

其實這些代碼我是在挺早之前寫的,今天在寫部落格的時候發現,其實桶就是一個隊列,所以上面的 R_Sort()函數複雜了,我們使用 array_push() 和 array_shift() 來重寫該方法(當然,要類比隊列的話,用 SPL 提供的 splqueue 是最為恰當的,在這裡為了簡便我就不用了):

function R_Sort(array &$arr,$loop){    $tempArr = array();    $count = count($arr);    for($i = 0;$i < 10;$i ++){        $tempArr[$i] = array();    }    //求桶的index的除數    //如798個位桶index=(798/1)%10=8    //十位桶index=(798/10)%10=9    //百位桶index=(798/100)%10=7    //$tempNum為上式中的1、10、100    $tempNum = (int)pow(10, $loop - 1);    for($i = 0;$i < $count;$i ++){        //求出某位上的數字        $row_index = ($arr[$i] / $tempNum) % 10;        //入桶        array_push($tempArr[$row_index],$arr[$i]);    }    //還原回原數組中    $k = 0;    for($i = 0;$i < 10;$i ++){        //出桶        while(count($tempArr[$i]) > 0){            $arr[$k ++] = array_shift($tempArr[$i]);        }    }}

基數排序法是屬於穩定性的排序,其時間複雜度為O (nlog(r)m),其中r為所採取的基數,而m為堆數。

好了,到這裡基數排序就已經給大家介紹完了。這個演算法的總結主要是通過看網上的資料,所以就不再給出原作者了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.