基数排序
- 对一组数组按个位、十位、百位、...、最高位上的数字对这组数组进行排序。
算法流程
- 获取所要排序的数组中最大的元素,方便提取出最大的位数
int get_max(int a[],int n)
{
int maxn = a[0];
for(int i=1;i<n;i++)
maxn = max(maxn,a[i]);
return max;
}
-
然后获取后,就可以依次从低位到高位向数组进行一次次的处理
-
设exp为指数,代表当前要处理的位数,比如位数为1,exp=1;位数为2,exp=10;
-
只要
max/exp>0
,就代表exp仍未达到数字的顶端
for(exp=1;max/exp>0;exp*=10){ CountSort(a,n,exp); }
-
-
单个位置上的排序CountSort(int a[],int n,int exp)
-
材料:
-
桶排序:bucket[idx]表示的是idx在这个数组中有多少个
桶排序改装:bucket[idx]表示的是以idx(0...9)在
exp
位有多少个 -
前缀和:目的通过前缀和的处理将每个数字给区分开,也可以看成是把
exp
位上相同的数字的这一类数字锁在一定的区间,或者也可以看成赋予一定的权值给了这一类数字从而使得这一类数字与其他数字区分开来,并且通过同类的数字可以通过自己内部的减一操作来使得自己内部的数字也具有区分度。注意点,由于前缀和的关系,output如果不对其数组的下标进行减一的话,傻傻直接拿来用的话,是会和a的数组对不上的。
for(int i=1;i<10;i++) bucket[i]+=bucket[i-1];
-
output数组:用来储存数组,并最终对a进行覆盖。
output[bucket[a[i]/exp%10]] = a[i];
-
同类的数字获取区分度
bucket[a[i]/exp%10]--;
-
-
-
在较低位置获取比较靠前的位置(相比于其他数字,会比较小),在较高位置的排序中也会优先被排序(这就保证了在高位上的相同数字的数字的大小的准确性)。
比如(213,212在经过个位数的排序后会先变成212,213,然后在十位上的排序,212相对于213会获得较先被排序的机会)
#include<bits/stdc++.h>
using namespace std;
int get_max(int a[],int alen)
{
int maxn = a[0];
for(int i=1;i<alen;i++)
maxn = max(maxn,a[i]);
return maxn;
}
void count_sort(int a[],int alen,int exp)
{
int bucket[10],output[alen];
memset(bucket,0,sizeof(bucket));
for(int i=0;i<alen;i++)
{
bucket[a[i]/exp%10]++;
}
for(int i=1;i<10;i++)
bucket[i]+=bucket[i-1];
for(int i=alen-1;i>=0;i--)//反着来
{
output[bucket[a[i]/exp%10]-1]=a[i];//这里有个减一,要使得output数组最终和buckets数组对上
bucket[a[i]/exp%10]--;
}
for(int i=0;i<alen;i++)
a[i] = output[i];
}
void radix_sort(int a[],int alen)
{
int exp;
int maxn = get_max(a,alen);
for(exp=1;maxn/exp>0;exp*=10)
count_sort(a,alen,exp);
}
int main()
{
int a[] = {53, 3, 542, 748, 14, 214, 154, 63, 616};
int alen = sizeof(a)/sizeof(a[0]);
puts("radix_sort前");
for(int i=0;i<alen;i++)
cout<<a[i]<<" ";
cout<<endl;
radix_sort(a,alen);
puts("radix_sort后");
for(int i=0;i<alen;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
其他
获取数组长度
int ilen = (sizeof(a)/sizeof(a[0]));