oj 2758: C++習題-基數排序

問題:

 

Description

基數排序是一種分配排序,其基本思想是:排序過程無須比較關鍵字,而是通過“分配”和“收集”過程來實現排序。它們的時間複雜度可達到線性O(n)。基數排序所做的事情,是對N位分別進行排序。從直覺上來看,人們可能會覺得應該首先按最高有效位進行排序,不過這點與我們的直覺相反,基數排序首先對最低有效位數字進行排序。如果我們每次比較r bits,則需要進行b/r趟,每趟進行計數排序需要O(n+2^r),則總的時間複雜度爲O(b/r(n+2^r))。

理論上來說,基數排序的速度是幾種排序方法中最快的,可以達到O(N),而其它的排序算法最快也只有O(N*logN)。但是,基數排序需要佔用額外的空間,而且只支持整數進行排序。

#include <iostream>
#include <string.h>
using namespace std;
/* 獲取輸入數字的索引值,order指定需要獲取哪一位的索引,1代表個位,2代表十位,3代表百位 */
int get_index(int num, int order)
{
    while(--order)
        num/=10;
    return num%10;
}
/* 進行基數排序 */
void radix_sort(int arr[], int len, int dec, int order)
{
    int i, j;
    int index;                      /* 排序索引 */
    int tmp[1001];                  /* 臨時數組,用來保存待排序的中間結果 */
    int num[10];                    /* 保存索引值的數組 */
    memset(num, 0, 10*sizeof(int)); /* 數組初始清零 */
    memset(tmp, 0, len*sizeof(int));/* 數組初始清零 */
    if (dec < order)                /* 最高位排序完成後返回 */
        return;
    for (i=0; i<len; i++)
    {
        index = get_index(arr[i],order);    /* 獲取索引值 */
        num[index]++;                       /* 對應位加一 */
    }
    for (i=1; i<10; i++)
        num[i] += num[i-1];                 /* 調整索引數組 */
    for (i=len-1; i>=0; i--)
    {
        index = get_index(arr[i], order);/* 從數組尾開始依次獲得各個數字的索引 */
        j = --num[index];                   /* 根據索引計算該數字在按位排序之後在數組中的位置 */
        tmp[j] = arr[i];                    /* 數字放入臨時數組 */
    }
    for (i=0; i<len; i++)
        arr[i] = tmp[i];                                     /* 從臨時數組複製到原數組 */
/////////////////////////////////////////////////////////
       /*    這裏補充代碼   */
       /* 繼續按高一位的數字大小進行排序 */
/////////////////////////////////////////////////////////
    return;
}
int main()
{
    int i,n;
    int arr[1001];
    cin>>n;
    for(i=0; i<n; i++)
        cin>>arr[i];
    int dec=3;      /* 最多處理位數 */
    int order= 1;   /* 排序的位數,1代表個位、2代表十位、3代表百位 */
    /* 排序函數,從個位開始 */
    radix_sort(arr, n, dec, order);
    for (i=0; i<n; i++)
        cout<<arr[i]<<" ";
    cout<<endl;
    return 0;
}

 

Input

 輸入n和n個整數

Output

從小到大排序

Sample Input

10
2 1 3 4 6 5 7 9 8 10

Sample Output

1 2 3 4 5 6 7 8 9 10 

HINT

 

Source

邵英帥&OJ

基數排序思路:準備10個位置,編號0—9,先由個位開始,將個位的值與位置編號對應,得到一個序列,此時個位已經排好,然後再到十位,在之前序列的基礎上,將十位的值再與位置編號相對應,將十位排好,然後....直至達到所有數中的最高位,所得的序列就是排好的序列了。

 

例如:待排序列:23,234,51,440,99,47,8,3,36,55

第一次排個位(加粗爲位置編號):

0  440

1 51

2 

3 3 23

4 234

5 55

6 36

7 47

8 8

9 99

第二次排十位:

0 3 8

2 23

3 234 36

4 440 47

5 51 55

6

7

8

9 99

第三次排百位:

0 3 8 23 36 47 51 55 99

1

2 234 440

3

4

5

6

7

8

9

最後得到正確序列:3 8 23 36 47 51 55 99 234 440

 

此題代碼:

 

#include <iostream>
#include <string.h>
using namespace std;
/* 獲取輸入數字的索引值,order指定需要獲取哪一位的索引,1代表個位,2代表十位,3代表百位 */
int get_index(int num, int order)
{
    while(--order)
        num/=10;
    return num%10;
}
/* 進行基數排序 */
void radix_sort(int arr[], int len, int dec, int order)
{
    int i, j;
    int index;                      /* 排序索引 */
    int tmp[1001];                  /* 臨時數組,用來保存待排序的中間結果 */
    int num[10];                    /* 保存索引值的數組 */
    memset(num, 0, 10*sizeof(int)); /* 數組初始清零 */
    memset(tmp, 0, len*sizeof(int));/* 數組初始清零 */
    if (dec < order)                /* 最高位排序完成後返回 */
        return;
    for (i=0; i<len; i++)
    {
        index = get_index(arr[i],order);    /* 獲取索引值 */
        num[index]++;                       /* 對應位加一 */
    }
    for (i=1; i<10; i++)
        num[i] += num[i-1];                 /* 調整索引數組 */
    for (i=len-1; i>=0; i--)
    {
        index = get_index(arr[i], order);/* 從數組尾開始依次獲得各個數字的索引 */
        j = --num[index];                   /* 根據索引計算該數字在按位排序之後在數組中的位置 */
        tmp[j] = arr[i];                    /* 數字放入臨時數組 */
    }
    for (i=0; i<len; i++)
        arr[i] = tmp[i];                                     /* 從臨時數組複製到原數組 */
    radix_sort(arr, len, dec, order+1);
    /*    這裏補充代碼   */
    /* 繼續按高一位的數字大小進行排序 */
    return;
}
int main()
{
    int i,n;
    int arr[1001];
    cin>>n;
    for(i=0; i<n; i++)
        cin>>arr[i];
    int dec=3;      /* 最多處理位數 */
    int order= 1;   /* 排序的位數,1代表個位、2代表十位、3代表百位 */
    /* 排序函數,從個位開始 */
    radix_sort(arr, n, dec, order);
    for (i=0; i<n; i++)
        cout<<arr[i]<<" ";
    cout<<endl;
    return 0;
}


小結:學習了排序中的基數排序。

 

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