基數排序

基數排序(Radix Sorting)是一種與其他排序算法完全不同的排序方法,其他的排序算法都是通過關鍵字之間的比較和移動來完成的,而基數排序則不需要比較,而是採用一種多關鍵字的思想。

什麼是多關鍵字的思想呢?
給定一組數據,我可以先按個位的大小對所有數進行排序,然後再按十位進行排序,一直到最高位,這樣就可以使整組數據變得有效,這樣從最低位開始的方法稱爲最低位優先(Least Significant Digit first)

反之,如果先從最高爲的關鍵字開始,最後再比較最低位,則稱之爲最高位優先(Most Significant Digit first)

排序過程如下圖:
這裏寫圖片描述

經過一次放置和回收,得到的序列已經按個位有序了,接下來按照次低位再次進行放置和回收。
這裏寫圖片描述

由此可以看出,如果一組序列中最大的數爲兩位數,則需要兩次的分配和收集,整個分配收集的次數與最大數的位數有關。

求最大位數:

int GetMaxBit(int* array,int size)
{
    assert(array);
    int base = 10;
    int digits = 1;//至少是個位數
    for(int i = 0;i < size;++i)
    {
        while(array[i] >= base)//只要有數大於base,則位數+1
        {
            ++digits;
            base *= 10;
        }
    }
    return digits;
}

基數排序需要兩個輔助空間,一個是0~9號桶,另一個是計算定位的數組,定位數組是幹什麼的呢?就是記錄每個桶中的數據待會要放回原數組的哪個位置。
這裏寫圖片描述

下面是代碼實現:

void RadixSort(int* array,int size)
{
    assert(array);
    int* buckets = new int[size];
    int base = 1;
    int maxbit = GetMaxBit(array,size);
    for(int i = 0;i < maxbit;++i)
    {
        //統計0~9號桶中的個數
        int counts[10] = {0};
        for(int i = 0;i < size;++i)
        {
            int num = (array[i]/base)%10;
            counts[num]++;
        }

        //定位數組
        int start[10] = {0};
        for(int i = 1 ;i < 10;++i)
        {
            start[i] = start[i - 1] + counts[i - 1];
        }

        //往桶裏扔
        for(int i = 0;i < size;++i)
        {
            int num = (array[i]/base)%10;
            int& pos = start[num];
            buckets[pos] = array[i];
            ++pos;
        }

        memcpy(array,buckets,sizeof(int)*size);
        base *= 10;
        delete[] buckets;
    }
}

時間複雜度:
基數排序的時間複雜度可以理解爲O(d*n),d爲序列中最大的位數,適用於n值很大,但是關鍵字較小的序列。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章