radixsort

基数排序

基数排序不是比较排序。用max表示输入数据中最大的数据,用k表示max的长度(代表其值的字符序串的长度),那么基数排序将执行k次循环,每次循环都比较这k位数据中的某一位,并按照该位数据大小排序,其结果是:该位相同的数据连续地存放到一块(在同一个桶中),该位不相同的数据是有序的(不同的桶中的数据是有序的)。循环深度增长的方向可以是从数据最低位数字向最高位数字方向,也可以反过来。

对于int类型数据,我们一般从低位往高位排序;对于字符串类型,从两个方向排序都很方便。

算法描述:
输入:元素个数n和数组a。
输出:数组a的元素按升序排列。
步骤:开辟数组b[n],用于保存每次循环之后的结果;
      开辟bucket_aux[10];辅助的
      开辟bucket[10],用于保存每一个桶(总共10个桶)的地址范围;
      开辟变量 i,max,exp;
      
      max <- a的最大元素
      exp <- 1;
      while max/exp > 0
          每个桶都初始化为0
          for i <- 0 to n-1
              bucket[a[i]/exp%10]++;/* 记住每个桶中的元素个数 */
          for i <- 0 to 9
              bucket_aux[i] <- bucket[i]; /*暂存到 bucket_aux */
          for i <- 1 to 9
              bucket[i]+=bucket[i-1]; /* 每个桶的地址上限 */
          for i <- 0 to 9
              bucket[i]-=bucket_aux[i]; /* 每个桶的起始地址 */
          for i <- 0 to n-1  /*扫描数组a,将每个元素放到桶中的相应位置*/
              b[bucket[a[i]/exp%10]++] = a[i]; 
          for i <- 0 to n-1
              a[i] <- b[i];
          exp *= 10;
      输出数组a;

时间复杂度:O(n)

空间复杂度:O(n)


C语言实现如下:

/* radixsort.c */
#include <stdio.h>
#include <assert.h>
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* memset(), memcpy() */
#define DEBUG1

void radixsort (int a[], int n){
    int * b;
    int bucket[10], bucket_aux[10];
    int i;
    int exp;
    int max;

    b = (int *) malloc (sizeof (int) * n);
    assert (NULL!=b);

    /* find the maximal element of array a */
    for (i=1,max=a[0]; i<n; i++){
        if (max<a[i]){
            max=a[i];
        }
    }

    /* loop for k times, k is the length of max */
    exp=1;
    while (max/exp){
        /* initialize buckets */
        memset (bucket, 0, 10*sizeof (int));
        /* record the number of items for each bucket */
        for (i=0; i<n; i++){
            bucket[a[i]/exp%10]++;
        }
        /* copy buckets to an auxiliary array */
        memcpy (bucket_aux, bucket, 10*sizeof (int));
        /* the address upper bound for each bucket */
        for (i=1; i<10; i++){
            bucket[i]+=bucket[i-1];
        }
        /* the address least bound for each bucket */
        for (i=0; i<10; i++){
            bucket[i]-=bucket_aux[i];
        }
        /* put each element of array a into its bucket */
        for (i=0; i<n; i++){
            b[bucket[a[i]/exp%10]++]=a[i];
        }
        /* get the number return to a */
        for (i=0; i<n; i++){
            a[i]=b[i];
        }
        exp*=10;
    }
    if (b){
        free (b);
    }
}

int main(int argc, char *argv[]){
    int i,n,*a;
#ifdef DEBUG1
    FILE * filein = freopen ("out.txt", "r", stdin);
#endif
    scanf ("%d",&n);
    assert (n>0);

    a = (int *) malloc (sizeof (int) * n);
    assert(NULL!=a);
    
    for (i=0; i<n; i++){
        scanf ("%d", &a[i]);
    }

    for (i=0; i<n; i++){
        printf ("%d\t", a[i]);
        if (9==i%10){
            puts ("");
        }
    }
    puts ("");

    radixsort (a,n);

    puts ("after radixsorting.");
    for (i=0; i<n; i++){
        printf ("%d\t", a[i]);
        if (9==i%10){
            puts ("");
        }
    }
    puts ("");    

#ifdef DEBUG1
    fclose (filein);
#endif

    if (a){
        free (a);
    }

    return 0;
}

/* a more brief implementation from Wikipedia */
void radixsort (int a[], int n){
    int * b;
    int bucket[10];
    int i;
    int exp;
    int max;

    b = (int *) malloc (sizeof (int) * n);
    assert (NULL!=b);

    /* find the maximal element of array a */
    for (i=1,max=a[0]; i<n; i++){
        if (max<a[i]){
            max=a[i];
        }
    }

    /* loop for k times, k is the length of max */
    exp=1;
    while (max/exp){
        /* initialize buckets */
        memset (bucket, 0, 10*sizeof (int));
        /* record the number of items for each bucket */
        for (i=0; i<n; i++){
            bucket[a[i]/exp%10]++;
        }
        /* the address upper bound for each bucket */
        for (i=1; i<10; i++){
            bucket[i]+=bucket[i-1];
        }
        /* put each element of array a into its bucket */
        for (i=n-1; i>=0; i--){
            b[--bucket[a[i]/exp%10]]=a[i];
        }
        /* get the number return to a */
        for (i=0; i<n; i++){
            a[i]=b[i];
        }
        exp*=10;
    }
    if (b){
        free (b);
    }
}

25032  9848  21392  6018  29677  2069  10455  25237  1595  31186  

25032  21392  10455  1595  31186  29677  25237  9848  6018  2069  

6018  25032  25237  9848  10455  2069  29677  31186  21392  1595  

6018  25032  2069  31186  25237  21392  10455  1595  29677  9848  

10455  31186  21392  1595  2069  25032  25237  6018  29677  9848  

1595  2069  6018  9848  10455  21392  25032  25237  29677  31186  

after radixsorting.

1595  2069  6018  9848  10455  21392  25032  25237  29677  31186  


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值