基数排序:
基数排序是一种线性的排序算法。设n个元素不超过d位,而且每位都介于0到9之间。基本思想是把最高位或(最低位)的数字看做第一关键字,次高位(次低位)数字看作是排序的第二关键字,一次类推..。
比如: 26 25 43 12 5 33 (按着次低位)
先有十个桶:0 1 2 3 4 5 6 7 8 9 或m个桶0<m<=10;
按个位 ---> (12) (33 ,43) (25,5) (26) 最低的位数一次放入相应的编号的桶里。
再一次取出:12 33 43 25 5 26.
在按十为---> (05) (12) (25) (26) (33,43) 记住是在上次的基础上,一次放入桶里。
取出:5 12 25 26 33 43 。排序就结束了。
可以看出排序的时间复杂度与最高位有关,故有:O(d(n+radix)
代码实现:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
void RadixCountSort(int *npidex,int *npdate,int n) //统计基数个数并排序(桶排序)
{
int i,npcount[10]; //基数只有十个 (十个桶)
memset(npcount,0,sizeof(npcount));
for(i=0;i<n;i++) npcount[npidex[i]]++; //统计基数相同的个数。
for(i=1;i<10;i++) npcount[i]+=npcount[i-1]; //确定不大于该位置i的个数
int *npsort=new int[n];
for(i=n-1;i>=0;i--) npsort[--npcount[npidex[i]]]=npdate[i]; //按桶的编号放入
for(i=0;i<n;i++) npdate[i]=npsort[i]; //依次从小到大取出桶里的数
delete npsort;
}
void RadixSort(int *npDate,int n) //基数排序
{
int *npDateRadix=new int[n];
int base=1,flag=0;
while(flag==0){
flag=1;
base*=10;
for(int i=0;i<n;i++){
npDateRadix[i]=npDate[i]%base;
npDateRadix[i]/=base/10;
if(npDateRadix[i]>0) flag=0;
}
if(flag) break; //如果最大的数的第一个位数为零,排序结束。
RadixCountSort(npDateRadix,npDate,n);
}
delete npDateRadix;
return;
}
int main(){
int n,date[1000];
while(cin>>n){
for(int i=0;i<n;i++)
cin>>date[i];
RadixSort(date,n);
for(int i=0;i<n;i++)
printf("%d ",date[i]);
printf("\n");
}
return 0;
}
/*
12
234 232 34 64 24 6765 13 466 13 99 2546 5
*/
学以致用:下面以HDU·1106为列。看下基数排序的速度。
基数排序(0ms) 快排(0ms)能自己否手写快排?
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
void RadixCountSort(int *npidex,long long *npdate,int n)
{
int i,npcount[10];
memset(npcount,0,sizeof(npcount));
for(i=0;i<n;i++) npcount[npidex[i]]++;
for(i=1;i<10;i++) npcount[i]+=npcount[i-1];
int *npsort=new int[n];
for(i=n-1;i>=0;i--) npsort[--npcount[npidex[i]]]=npdate[i];
for(i=0;i<n;i++) npdate[i]=npsort[i];
delete npsort;
}
void RadixSort(long long *npDate,int n)
{
int *npDateRadix=new int[n];
int base=1,flag=0;
while(flag==0){
flag=1;
base*=10;
for(int i=0;i<n;i++){
npDateRadix[i]=npDate[i]%base;
npDateRadix[i]/=base/10;
if(npDateRadix[i]>0) flag=0;
}
if(flag) break;
RadixCountSort(npDateRadix,npDate,n);
}
delete npDateRadix;
return;
}
int main()
{
char st[1005],*p;
int i,num,flag,cnt;
long long a[1005];
while(scanf("%s",st)!=EOF){
memset(a,0,sizeof(a));
cnt=0,flag=0,num=0;
for(p=st;*p;p++){
if(*p!='5'){
num=num*10+(*p-'0');
flag=1;
}
else{
if(flag){
a[cnt++]=num;
num=0;
flag=0;
}
}
}
if(num) a[cnt++]=num;
// sort(a,a+cnt);
RadixSort(a,cnt);
for(i=0;i<cnt;i++)
printf(i==0?"%d":" %d",a[i]);
printf("\n");
}
}
贴下快排函数的代码:
#include <stdio.h>
int patition(int a[], int p, int r) //模板
{
int i = p-1;
for (int j = p; j <= r-1; ++j)
{
if (a[j] < a[r])
{
++i;
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
int t = a[i+1];
a[i+1] = a[r];
a[r] = t;
return i+1;
}
void quicksort(int a[], int p, int r)
{
if (p < r)
{
int q = patition(a, p, r);
quicksort(a, p, q-1);
quicksort(a, q+1, r);
}
}
int main()
{
int N,A[1000];
while (1)
{
printf("请输入要排序的元素个数:");
scanf("%d", &N);
for (int i = 1; i <= N; ++i)
scanf("%d", &A[i]);
quicksort(A, 1, N);
for ( i = 1; i <= N; ++i)
printf("%d ", A[i]);
puts("");
}
return 0;
}
总的来说基数排序要稍好于快排。