排序:基数排序(C)

1.思想

1.1 例子

在这里插入图片描述

1.2.思想介绍

1.基数排序是在箱排序的基础之上进行扩展和完善的
2.通过判断待排序的数组中的位数,决定进行创建箱子的个数和遍历的次数.
例如:待排序中最多的位数为3位,那么就需要创建三个箱子(当然也可以创建两个,进行复用,记得复用之前要清除之前的箱子),这里我就不复用了.那么需要进行遍历三次
3.开始排序(就是遍历装箱操作)
3.1:第一次遍历待排序的数组.进行第一次装箱(箱子A),按照个数进行装到对应的箱子.
3.2:第二次顺序遍历前面的箱子(箱子A),进行第二次装箱(箱子B),按照十位数进行装到对应的箱子中.
3.3:第三次顺序遍历前面的箱子(箱子B),进行第三次装箱(箱子C),按照百位数进行装到对应的箱子中.

到了这里已经排序完成,还差最后一步.
4.组装数据,顺序遍历最后一次的箱子(箱子C).存储到一个数组中,此时数组中的数据就是已经排序好的.

在这里插入图片描述
例如:上面的箱子,顺序遍历这个箱子A存储到箱子B中.(按照十位存储)
读取0号桶:
第一个数:200, 十位为0, 存储箱子B中0号桶[200]
第二个数:100, 十位为0, 存储箱子B中0号桶[200,100]
读取1号桶:
第一个数:211, 十位为1, 存储箱子B中1号桶[211]
读取2号桶:
没有值跳过
读取3号桶:
第一个数:143, 十位为4, 存储箱子B中4号桶[143]
第二个数:433, 十位为3, 存储箱子B中3号桶[433]
读取4号桶:
第一个数:84, 十位为4, 存储箱子B中8号桶[84]
第二个数:134, 十位为3, 存储箱子B中3号桶[433,134]
第三个数:534, 十位为3, 存储箱子B中3号桶[433,134,534]
第四个数:994, 十位为9, 存储箱子B中9号桶[994]
…后面的就不一一举例了.直到遍历结束.

2.运行结果

在这里插入图片描述

3.算法实现

3.1 定义数据结构

#define  MAX_COUNT 10

//链表结点 顺序存储箱子中数值,这样就可以不用限制数据量.
typedef struct SNode{
    int  value;
    struct SNode * next;
}Node;
//箱子中的每个链表
typedef struct List{
    int key;
    Node *header;//头指针
    Node *rear;//尾指针
}LinkList;
//箱子列表
typedef struct RadixBox{
    LinkList * boxs[MAX_COUNT];
}RB;

3.2 定义方法集合

//入队
void InsertList(LinkList *list,int value);
//打印队列
void logList(LinkList *list);
//打印箱子
void  logRadixBox(RB rb);
//打印箱子--数组类型
void  logRadixBoxArray(RB rb);
//装箱操作
//type:1->除数为1*10  2:除数为2*20
void EnRadixBox(int type,RB rb,int value);
//基数排序
void  RadixSort(void);

下载的源码中少了这个方法:logRadixBoxArray(),可以添加上,也可以不加,这是多打印了每次装箱后的数组.

3.3 方法实现


//打印队列
void logList(LinkList *list){
    //先判断列表是否为空
    if(list!=NULL){
        Node *p=list->header;
        printf("[");
        int first=1;
        while (p!=NULL) {
            if(first==1){
                first=0;
                printf("%d",p->value);
            }else{
                printf(",%d",p->value);
            }
            p=p->next;
        }
        printf("]\n");
    }
}

//打印箱子
void  logRadixBox(RB rb){
    printf("********************************\n");
    int  i;
    for(i=0;i<MAX_COUNT;i++){
        printf("[%d]->",rb.boxs[i]->key);
        logList(rb.boxs[i]);
    }
    logRadixBoxArray(rb);
    printf("********************************\n");
}
//打印箱子--数组类型
void  logRadixBoxArray(RB rb){
    Node  *p;
    int i=0;
    int  j;
    printf("装箱后的数组:[");
     for(j=0;j<MAX_COUNT;j++){
         p= rb.boxs[j]->header;
         while (p!=NULL) {
             if(i==0)
             {
                 printf("%d",p->value) ;
                 i=1;
             }
             else
               printf(",%d",p->value) ;
            p=p->next;
         }
     }
      printf("]\n");
}

//入队
void InsertList(LinkList *list,int value){
    //1.创建插入的结点
    Node *p=(Node *)malloc(sizeof(Node));
    p->value=value;
    p->next=NULL;
    //2.判断链表是否为NULL
    if(list==NULL){
        list=(LinkList *)malloc(sizeof(LinkList));
        list->header=NULL;
        list->rear=NULL;
    }
    //3.将新的结点插入链表
    if(list->header==NULL){
        list->header=p;
    }
    if(list->rear==NULL){
       list->rear=p;
    }else{
        list->rear->next=p;
        list->rear=p;
    }
}

//装箱操作
//type->0:个数,1:十位,2:百位的余数
void EnRadixBox(int type,RB rb,int value){
    //1.type必须从1开始
    if(type<0){
        return;
    }
    //2.计算位置
    //134: 134%10
    //134: (134/10)%10
    //134: (134/100)%10
    //(value/(pow(10,type)))%10
    int position= ((int) (value/(int)pow(10, type)))%10;
    LinkList *list= rb.boxs[position];
    InsertList(list,value);
}

//基数排序
void  RadixSort(void){
    int i;
    int j;
    int n=19;
    //1.初始化待排序的数组
    int array[]={76,84,134,196,177,143,696,534,599,211,433,200,994,459,635,179,100,26,284};
    printf("未排序:");
    logArray(array, n);
    //2.首先要知道数组中最大的是几位数,就需要几个箱子,从个位到最高位顺序装箱
    //初始化箱子
    RB rbs[3];
    //初始化三个箱子
    for(i=0;i<3;i++){
        for(j=0;j<MAX_COUNT;j++){
            rbs[i].boxs[j]=(LinkList *)malloc(sizeof(LinkList));
            rbs[i].boxs[j]->key=j;
            rbs[i].boxs[j]->header=NULL;
            rbs[i].boxs[j]->rear=NULL;
        }
    }
    //3.开始装箱
    for(i=0;i<3;i++){
        if(i==0){//第一次是遍历排序数组,装箱
            for(j=0;j<n;j++){
                //个位
                EnRadixBox(i,rbs[i],array[j]);
            }
            logRadixBox(rbs[i]);
        }else{//之后就是遍历前一个箱子进行装箱
            //遍历前一个箱子,装在当前箱子
           RB rbPre=rbs[i-1];
            for(j=0;j<MAX_COUNT;j++){
                if(rbPre.boxs[j]!=NULL){
                    Node *p=rbPre.boxs[j]->header;
                    while (p!=NULL) {
                        EnRadixBox(i,rbs[i],p->value);
                        p=p->next;
                    }
                }
            }
           logRadixBox(rbs[i]);
        }
    }
    //4.遍历最后一个箱子装入数组,就是排好序的
    Node  *p;
    i=0;
     for(j=0;j<MAX_COUNT;j++){
         p= rbs[2].boxs[j]->header;
         while (p!=NULL) {
             array[i++]=p->value;
             p=p->next;
         }
     }
      printf("已排序:");
      logArray(array, n);
}

3.4 另外的实现思路

我这里循环遍历的时候,第一次是遍历待排序的数据,然后进行装箱,剩下的顺序遍历,是遍历上一次的箱子.
优化点:
1.创建箱子的时候,可以创建一个个箱子
2.每次装完箱子操作后,可以先顺序遍历箱子,顺序存储到数组中.然后下一次遍历的时候,是遍历装箱后的数组.这样就是每次都是遍历数组,进行装箱.
3.在决定循环几次的时候,我这里知道待排序中的数组,最大的是3位数,
3.1这里可以写一个快速查找方法,寻找最大位数,或者最大值.
3.2或者是在第一次装箱的时候,同时查找最大位数(N)也可以,这样后面循环的就是再进行(N-1)次.

源码下载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值