桶排序&&基数排序

桶排序

在谈到基数排序之前我想先说一下桶排序,因为基数排序是桶排序的推广。
桶排序——最快最简单的排序
桶排序:
假设你要排序的数是0~N,那么你需要开辟一个大小为N的数组num,并且将此数组中所有元素初始化为0,接下来请遍历你想要排序的数,将num数组对应下标等于序列中的数字的元素加1,最后你只需要遍历num数组,假如num[i]=n,那么你只需要将i打印n次即可。
下面是桶排序的示例:

int *bucket_sort(const int a[], int len)
{
    int num[1000];
    for (int i = 0; i < 1000; i++)
        num[i] = 0;
    for (int i = 0; i < len; i++) {
        num[a[i]]++;
    }
    int *p = num;
    return p;
}

至此,桶排序的优缺点我们其实已经一目了然了
优点:简单明了,易于思考,最快最简单的排序
缺点:太过于浪费空间了,比如你想要排列0,1,3,2,5,99999,很明显,按照上述的方法你需要开辟99999这么大的一个数组,显然这是不现实且没有必要的浪费空间的行为。
那么,为了解决这个问题,便有了基数排序。

基数排序

基数排序是桶排序的推广,假设我们有10个数需要排序,这10个数的范围在0~999之间,我们将其排序,999还好,但是如果是9999999呢?显然我们是不能够使用桶排序的,那样是不现实的。
我们的策略是:多趟桶排序基数排序,基数排序分为最低位优先基数排序(LSD)和最高位优先基数排序(MSD),在这里我将就低位基数排序来谈基数排序,高位基数排序同理。
下面例子说明10个数的基数排序的具体做法,假设输入为,64,8,216,512,27,729,0,1,343,125.
第一趟桶排序的结果(个位桶排序)
在这里插入图片描述第二趟桶排序的结果(十位桶排序)
在这里插入图片描述第三趟桶排序的结果(百位桶排序)
在这里插入图片描述为了使得算法得出正确的结果,要注意唯一可能出错的地方就是如果两个数出自同一个桶中但顺序却是错误的,不过,只要我们保证前面各趟排序当几个数进入同一个桶时,它们是以排序好的顺序状态进入的即可。
下面的例子是我基于链表实现的,这个实现个人觉得并不是比较好,后续我将会更改为更加巧妙的实现方法。

#ifndef RADIX_H
#define RADIX_H

#define NUM_LEN 10

typedef struct value {
    int bucket_num;
    int num[NUM_LEN];
    int numi;
} value_t;            

typedef struct node {  
    value_t *value;       
    struct node *next;
} node_t;              

int *radix_sort(int a[], int len);

#endif
#include "radix.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define NUM_LEN 10

node_t *create_bucket()
{
    node_t *dummy = (node_t *)malloc(sizeof(node_t));
    node_t *tmp = dummy;
    int loop = 10, i = 0;
    while (loop--) {
        node_t *node = (node_t *)malloc(sizeof(node_t));
        node->value = (value_t *)malloc(sizeof(value_t));
        tmp->next = node;
        tmp = node;
        node->value->numi = 0;
        node->value->bucket_num = i;
        i++;
        for (int j = 0; j < NUM_LEN; j++) {
            node->value->num[j] = 0;
        }
    }
    tmp->next = NULL;
    return dummy;
}

void read_clear_bucket(int a[], node_t *h)
{
    int j = 0;                                      
    node_t *tmp = h->next;                                  
    while (tmp != NULL) {                           
        for (int i = 0; i < tmp->value->numi; i++) {
            a[j++] = tmp->value->num[i];            
            tmp->value->num[i] = 0;
        }                                           
        tmp->value->numi = 0;                       
        tmp = tmp->next;                            
    }                                               
}

int *radix_sort(int a[], int len)
{
    node_t *h = create_bucket(); 
    int li = 0;
    node_t *tmp = h->next;
    for (int i = 0; i < len; i++) {
        tmp = h->next;
        if (a[i] >= 0 && a[i] < 10) {
            li = a[i];
        } else if (a[i] >= 10 && a[i] < 100) {
            li = a[i]%10;
        } else if (a[i] >= 100 && a[i] < 1000) {
            li = a[i]%10;
        }
        while (li != tmp->value->bucket_num) {
            tmp = tmp->next;
        }
        tmp->value->num[tmp->value->numi] = a[i];
        tmp->value->numi++;
    }
    read_clear_bucket(a, h);
//---------------------------------------------------------------------------------------
    for (int i = 0; i < len; i++) {              
        tmp = h->next;                           
        if (a[i] >= 0 && a[i] < 10) {            
            li = 0;                           
        } else if (a[i] >= 10 && a[i] < 100) {   
            li = a[i]/10;                        
        } else if (a[i] >= 100 && a[i] < 1000) { 
            li = a[i]%100/10;                        
        }                                        
        while (li != tmp->value->bucket_num) {   
            tmp = tmp->next;                     
        }                                        
        tmp->value->num[tmp->value->numi] = a[i];
        tmp->value->numi++;                      
    }                                            
    read_clear_bucket(a, h);                     
//--------------------------------------------------------------------------------------
    for (int i = 0; i < len; i++) {              
        tmp = h->next;                           
        if (a[i] >= 0 && a[i] < 10) {            
            li = 0;                              
        } else if (a[i] >= 10 && a[i] < 100) {   
            li = 0;                        
        } else if (a[i] >= 100 && a[i] < 1000) { 
            li = a[i]/100;                    
        }                                        
        while (li != tmp->value->bucket_num) {   
            tmp = tmp->next;                     
        }                                        
        tmp->value->num[tmp->value->numi] = a[i];
        tmp->value->numi++;                      
    }                                            
    read_clear_bucket(a, h);                    
    return a;
}                        

参考文献:《数据结构与算法——C语言描述》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值