[C语言][排序(6)]基数排序

1.基数排序(次位优先LSD)

首先根据基数进行建桶,比如10进制,我们就建立10个桶,{0,1,2,...,9}

以输入序列: 64, 8, 216, 512, 27, 729, 0, 1, 343, 125为例

第一轮根据个位数的值,分别放入相应的桶中:

进行完这一轮之后,我们根据放入桶中的顺序,用链表串起来,进行第二轮,根据十位数放入相应位置:

 

然后根据放入桶中的顺序,再次用链表串起来,在它上面进行第三轮:根据百位数:

然后我们再用链表按顺序串起来,我们发现已经有序了,为了保险,我们可以再进行一轮,然后遍历链表,将值放回数组就可以。

#define Maxsize 1000
#define Radix 10
#define MaxDigit 4
typedef struct Node *ptrnode;
struct Node
{
    int key;
    ptrnode next;
};
struct NodeBucket
{
    ptrnode head,tail;
};
typedef struct NodeBucket Bucket[Maxsize];
int getnum(int x,int d)
{
    int i,y;
    for(i=1;i<=d;i++)
    {
        y=x%Radix;//取一位数
        x=x/Radix;
    }
    return y;
}
void LSD(int a[],int n)
{
    ptrnode head,tmp,p;
    head=NULL;
    Bucket B;
    int i;
    for(i=0;i<n;i++)//从头插入元素
    {
        tmp=(ptrnode)malloc(sizeof(struct Node));
        tmp->next=head;
        tmp->key=a[i];
        head=tmp;
    }
    //设立10个桶{0,1,2,3,4,..9} 假设最大有4位数
    int D,Di,ans;
    for(D=1;D<=MaxDigit;D++)
    {
        p=head;//记录所有元素的链表
        while(p!=NULL)
        {
            tmp=p;
            Di=getnum(tmp->key,D);//取出一位数
            p=p->next;//从链表中删除tmp
            tmp->next=NULL;
            //将元素放入相应的桶中
            if(B[Di].head==NULL)
            {
                B[Di].head=B[Di].tail=tmp;
            }
            else
            {
                B[Di].tail->next=tmp;
                B[Di].tail=tmp;//tail指向末尾
            }
        }
        //第一轮将元素放入桶中之后进行元素的收集,也就是用一个链表串起来
       //由于采取的是头插法 所以我们倒着来插入
        head=NULL;
        for(Di=Radix-1;Di>=0;Di--)
        {
            if(B[Di].head!=NULL)
            {
                B[Di].tail->next=head;
                head=B[Di].head;
                B[Di].head=B[Di].tail=NULL;//清空这个桶
            }
        }
        //现在head里存放的是按照第一轮排序顺序存放的数值,进行新一轮排序
    }
    //排序结束,把所有值放回数组
    for(i=0;i<n;i++)
    {
        tmp=head;
        a[i]=tmp->key;
        head=head->next;
        free(tmp);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值