1. 程式人生 > >基數排序-C語言實現

基數排序-C語言實現

基數排序(radix sorting)屬於“分配式排序”(distribution sort),又稱“桶子法”(bucket sort)的穩定性排序法。基數排序的方式可以採用最低有效位LSD(Least significant digital)或最高有效位MSD(Most significant digital)。LSD的排序方式將所有待比較數值統一為同樣的數位長度,數位較短的數前面補零。 然後 從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後, 數列就變成一個有序序列。而MSD則相反,由最高位開始,先按最高位排序分組,同一組中記錄,最高位相等,再對各組按次高位排序分成子組,之後,對後面的位繼續這樣的排序分組,直到各子組排序完成。再將各組連線起來,便得到一個有序序列

。下面以一組數為例:{90,100,204,20,32,19,56,48,3,91,94,90},採用LSD方式:

0  90 100 20 90                                                                 0   100 3(3在排序前要填充為003)204

1  91                                                                                  1    

2  32                                                                                   2  20                      

3  3   按最低位排序結果{90 100 20 90 91 32 3 204 94 56 48}   3   32   得到第二次排序結果{100 3 204 20 32 48 56 90 90 91 94}

4  204 94            -------------》                                          4   48    -------------------》

5                                                                                          5   56

6  56                                                                                    6    

7                                                                                          7   

8  48                                                                                    8   

9                                                                                          9    90 90 91 94

----------------------------------------------------------------------------------------------------------------------------------------------------------

       0   3  20  32 48 56 90 90 91 94  {用0填充了最高位)

1   100

2   204

3                              第三次排序結束(最高有3位數)

4                     --------------------------------->   {3 20 32 48 56 90 90 91 94 100 204} 有序序列

5

6

7

8

9

LSD的基數排序適用於位數小的數列,如果位數多的話,使用MSD的效率會比較好。MSD的方式與LSD相反,是由高位數為基底開始進行分配,但在分配之後並不馬上合併回一個陣列中,而是在每個“桶子”中建立“子桶”,將每個桶子中的數值按照下一數位的值分配到“子桶”中。在進行完最低位數的分配後再合併回單一的陣列中,下一篇部落格會介紹。

C語言實現:(程式碼來自網際網路)

#include<stdio.h>
#include<stdlib.h>
int maxbit(int data[], int n) //輔助函式,求資料的最大位數
{
    int d = 1; //儲存最大的位數
    int p = 10;
    for(int i = 0; i < n; ++i) {
        while(data[i] >= p) {
            p *= 10;
            ++d;
        }
    }
    return d;
}
void radixsort(int data[], int n)   //基數排序
{
    int d = maxbit(data, n);   //陣列中的元素的最大位數
    int *tmp = (int *)malloc(n * sizeof(int));
    int *count = (int *)malloc(10 * sizeof(int));   //計數器
    int i, j, k;
    int radix = 1;
    for(i = 1; i <= d; i++) {   //進行d次排序
        for(j = 0; j < 10; j++)
            count[j] = 0;    //每次分配前清空計數器
        for(j = 0; j < n; j++) {
            k = (data[j] / radix) % 10;   //計算每次迴圈某一位的數字
            count[k]++;    //統計每個桶中的記錄數
        }
        for(j = 1; j < 10; j++)
            count[j] = count[j - 1] + count[j];   //第j個桶以及之前所有桶中元素的總數
        for(j = n - 1; j >= 0; j--) {    //將所有桶中記錄依次收集到tmp中
            k = (data[j] / radix) % 10;
            tmp[count[k] - 1] = data[j];
            count[k]--;
        }
        for(j = 0; j < n; j++)   //將臨時陣列的內容複製到data中
            data[j] = tmp[j];
        radix = radix * 10;
    }
    free(tmp);
    free(count);
}
int main()
{
    int a[] = {90,100,204,20,32,19,56,48,3,91,94,90};
    int n;
    n = sizeof(a) / sizeof(a[0]);
    radixsort(a, n);
    for(int k = 0; k < n; k++)
        printf("%d ", a[k]);
    printf("\n");
    return 0;
}
時間效率:設待排序列為n個記錄,d個關鍵碼,關鍵碼的取值範圍為radix,則進行鏈式基數排序的時間複雜度為O(d(n+radix)),其中,一趟分配時間複雜度為O(n),一趟收集時間複雜度為O(radix),共進行d趟分配和收集。空間效率:需要2*radix個指向佇列的輔助空間,以及用於靜態連結串列的n個指標。