排序算法之基数排序

注意:以下都是按照升序讲的,降序的时候反过来就行。

基本思路:每次按照个位(十位,百位.........)对原始数组进行升序排序。

a数组:原始数据存储数组。

w数组:桶数组,有两个功能:第一个功能(用来记录位数上的数字出现的次数)第二个功能(用来记录该位上的数字如果为i时应该在a数组中的哪个位置),第二个功能的实现需要第一个功能的数据。

temp数组:和归并排序中的help数组功能基本一样,临时储存数据的功能

算法流程:

1:先求出所有数字中最大的位数,决定了下面排序几次

2:先按照个位数字排序,然后执行下面过程,执行完成后,跳回到这里,再按照十位(百位.......)排序,在执行下面过程。

3:按照排序结果改变a数组中的各个数字的位置

需要注意的是再往temp数组中放数(记为操作1)时,必须从a数组的最后往前推,具体原因看下面的图:

其实,第一次进行操作1的时候从前往后推和从后往前推是没有关系的,因为刚开始的a数组是无序的。
但是第二次和第二次以后进行操作1必须是从后往前推,(第二次进行操作1)因为这时a数组中在个位数上已经是有序的了,必须从后往前推,这样才能确保如果十位数字上的数相等的话个位数字上的数的顺序不会被改变。



代码如下:

#include<bits/stdc++.h>
using namespace std;
int w[10];//记录位数的数组
int a[9999];//记录输入的数据
int n;
int maxweishu()//这个函数是求输入的所有数据中最大位数的
{
    int d=0;
    int z=1;//通过z的累乘判断,如果z的10000,而a[i]是158,说明最大位数绝对不可能是三位,最小为4位
    for(int i=1;i<=n;i++)
    {
        while (a[i]>z)//如果这个条件满足,说明当前访问的数的位数大于已经访问过的前面的数的最大位数,那么就更新最大的位数
        {
            z=z*10;
            d++;
        }
    }
    return d;
}
void jishupaixu()//这是基数排序的核心
{
    int index=1;//通过index的累乘来找出个位,十位,百位.......上的数字
    int rex=maxweishu();//rex保存的是最大的位数,决定按位数进行排序排几次
    for(int i=1;i<=rex;i++)
    {
        memset(w,0,sizeof(w));//必须初始化w数组
        for(int i=1;i<=n;i++)
            w[(a[i]/index)%10]++;//找出当前位的值,并存在w数组中(功能1)
        for(int i=1;i<10;i++)
            w[i]=w[i]+w[i-1];//这个操作完成后,w数组中存的就是如果该位上数字为i时,应该在a数组中的哪个位置(功能2)
        int temp[9999];//和归并排序中help数组功能差不多,临时储存数字,然后复制到a数组中去
        for(int i=n;i>=1;i--)//必须从数组的最后一个数字往前推
        {
            temp[w[(a[i]/index)%10]]=a[i];
            w[(a[i]/index)%10]--;
        }
        for(int i=1;i<=n;i++)//将temp数组中的值复制到a数组中去,相当于对a数组中的数进行位置交换
            a[i]=temp[i];
        index*=10;
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    jishupaixu();
    for(int i=1;i<=n;i++)
        cout<<a[i]<<" ";
}

猜你喜欢

转载自blog.csdn.net/qq_40938077/article/details/80372402