C语言基数排序——顺序队列实现

基数排序


 

基本要求:

从键盘上输入n个程度为m的整数,要求输出这些整数的升序排列。


 

具体要求

  1. 使用的数据结构是队列,利用顺序队列来实现
  2. 有良好的人机交互
  3. 能够输出每一趟分配和收集的情况

基本概念:

基数排序属于分配式排序、又称桶子法。通过键值的查询,将要排序的元素分配至某些“桶”中,以达到排序的作用。


具体思想:

以整形为例,将整形10进制按每位拆分,然后从低位到高位依次比较

主要分为两个过程:

分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中

收集,再将放置在0~9号桶中的数据按顺序放到数组中

重复分配收集过程,从个位到最高位为重复次数


代码实现:

 

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

#define Radix 10          //代表Radix(10)个队列

typedef int QElemType;
typedef struct
{
    QElemType *base;       //初始化的动态分配空间,存储数据
    int front;              //头指针,指向队列头元素,用来移动
    int rear;               //尾指针,指向队列尾元素的下一位置,确定长度
} SqQueue;


//distribute进行第n趟分配
//原始数据保存在Q.base数组中
//ArrType是SqQueue类型的数组,
void distribute(SqQueue &Q,int n,SqQueue ArrType[])
{
    //quot-商
    //rem-存储每个数据的第n位(即第1位、第2位...第n位)的值
    int i,c,temp,quot,rem;
    //for置空Radix(10)个队列
    for(i=0; i<Radix; i++)
        ArrType[i].front=0;
    //for处理每个数据的第n位
    for(i=0; i<Q.rear; i++)
    {
        //将第i个数据暂存到quot
        quot=Q.base[i];
        c=0;
        //while计算第i个数据的第n位的值并保存到rem
        while(c<n)
        {
            c++;
            rem=quot%Radix;
            quot/=Radix;
        }
        //将第n位为rem的数据复制到第rem个队列
        //即根据数据的第n位的数字rem,将数据分配到第rem个队列的尾部
        ArrType[rem].base[ArrType[rem].front++]=Q.base[i];
    }
    printf("第%d趟分配之后的情况是:\n",n);
    for(i=0; i<Radix; i++)
    {
        temp=ArrType[i].front;
        //if如果第i个队列不为空
        if(temp>0)
        {
            printf("队列[%d]队头指针front->",i);
            for(c=0; c<temp-1; c++)
                printf("%d-",ArrType[i].base[c]);
            printf("%d<-队列[%d]队尾指针rear\n",ArrType[i].base[temp-1],i);
        }
    }
}

//collect进行第n趟收集
//ArrType保存了第n-1趟分配的结果
void collect(SqQueue &Q,int n,SqQueue ArrType[])
{
    //collected记录已收集数据的数量
    int i,collected=0;

    //for将数组ArrType中的数据收集到int型数组Q.base中
    for(i=0; i<Radix; i++)
    {
        //if如果第i个队列不空,就收集它的数据
        if(ArrType[i].front!=0)
        {
            //进行收集(简单地复制到Q.base数组就行了)
            memcpy(Q.base+collected,ArrType[i].base,ArrType[i].front*sizeof(int));
            collected+=ArrType[i].front;
        }
    }
    printf("第%d趟收集之后的情况是:\n",n);
    for(i=0; i<=Q.front-1; i++)
    {
        printf("%d ",Q.base[i]);
    }
    printf("\n\n");
}

//计算每个队列的初始长度(为数据量的1/Radix)
void Ord(SqQueue &Q,SqQueue ArrType[],int M)
{
    int i;
    int temp=M;

    for(i=0; i<Radix; i++)
    {
        //为第i个队列分配空间
        ArrType[i].base=(int*)calloc(temp,sizeof(int));
        ArrType[i].rear=temp;
    }
}

//for进行M(M为输入的每个数据的长度)趟分配和收集
void RadixSort(SqQueue Q,int M,SqQueue ArrType[])
{
    for(int i=1; i<=M; i++)
    {
        distribute(Q,i,ArrType);
        collect(Q,i,ArrType);
    }
}


int main()
{
    int i,M;
    SqQueue Q,ArrType[Radix];
    printf("请输入每个数据的长度:");
    scanf("%d",&M);
    printf("请输入共有多少个数据:");
    scanf("%d",&Q.rear);
    Q.base=(int*)calloc(Q.rear,sizeof(int));
    Q.front=0;
    printf("请输入%d个长度为%d的数据:\n",Q.rear,M);
    for(i=0; i<Q.rear; i++)
        scanf("%d",&Q.base[Q.front++]);
    printf("\n");
    Ord(Q,ArrType,M);
    RadixSort(Q,M,ArrType);
    //以下的free释放动态分配的内存
    free(Q.base);
    for(i=0; i<Radix; i++)
        free(ArrType[i].base);
    system("PAUSE");
    return 0;
}

 


数据处理:


尾言:

基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数

在某些时候,基数排序法的效率高于其它的稳定性排序法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值