基数排序
基数排序(桶排序)
基本思想:
是将阵列分别有限数量的桶子里。每个桶子再个别排序。桶排序是鸽巢排序的一种归纳结果。当要
被排序的数值是均匀分配的时候,桶排序使用线性时间(O(n));
桶排序的缺点:
1)首先是空间复杂度比较高,需要额外开销大。排序有两个数组空间开销,一个存放待排序数组,
一个就是所谓的桶,比如待排序值是从0到m-1,那就需要m个桶,这个桶组就要至少m个空间。
2)其次待排序的元素都要在一定范围内等等
桶式排序是一种分配排序。分配排序的特定是不需要进行关键码的比较,单前提是要知道待排序
序列的一些具体情况。
MSD:
#include<stdio.h>
#include<stdlib.h>
int getdigit(int x,int d)
{
int a[] = {1,1,10}; //因为待排序最大数据也只有两位数,所以在此只需要到十位就满足
return ((x/a[d])%10); //确定桶号
}
void PrintArr(int ar[], int n)
{
int i;
for(i=0;i<n; ++i)
printf("%d ",ar[i]);
printf("\n");
}
void msdradix_sort(int arr[],int begin,int end,int d)
{
const int radix = 10;
int count[radix] , i, j;
//置空
for(i=0; i<radix; ++i)
{
count[i] = 0;
}
//分配桶存储空间
int *bucket = NULL;
bucket = (int*)malloc((end-begin +1)*sizeof(int));
if(bucket == NULL)
printf("error!\n");
//统计各桶需要装的元素的个数
for(i=begin; i<=end; ++i)
{
int dd = getdigit(arr[i],d);
count[dd]++;
}
//求出桶的边界索引,count[i]值为第i个桶的右边界索引+1
for(i=1;i<radix; ++i)
{
count[i] = count[i] + count[i-1];
}
//这里要从右向左扫描,保证排序稳定性
for(i = end; i>=begin; --i)
{
j = getdigit(arr[i],d);//求出关键码的第d位的数字, 例如:576的第3位是5
bucket[count[j]-1] = arr[i];//放入对应的桶中,count[j]-1是第j个桶的右边界索引
--count[j];//第j个桶放下一个元素的位置(右边界索引+1)
}
//注意:此时count[i]为第i个桶左边界
//从各个桶中收集数据
for(i = begin,j=0;i<=end; ++i,++j)
{
arr[i] = bucket[j];
}
//释放存储空间
free(bucket);
bucket = NULL;
//堆各桶中数据进行再排序
for(i=0;i<radix; i++)
{
int p1 = begin + count[i]; //第i个桶的左边界
int p2 = begin + count[i+1] -1; //第i个桶的右边界
if(p1<p2 && d > 1)
{
msdradix_sort(arr,p1,p2,d-1); //对第i个桶递归调用,进行基数排序,数位降1
}
}
}
int main()
{
int ar[] = {12,14,54,5,6,3,9,8,47,89};
int len = sizeof(ar)/sizeof(int);
printf("sort befor:\n");
PrintArr(ar,len);
msdradix_sort(ar,0,len-1,2);
printf("sort after : \n");
PrintArr(ar,len);
return 0;
}
LSD:
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10000
int getdigit(int x,int d)
{
int a[] = {1,1,10,100};//最大三位数,所以这里只要百位就满足了
return (x/a[d])%10;
}
void PrintArr(int ar[],int n)
{
int i;
for(i =0;i<n; ++i)
{
printf("%d ",ar[i]);
}
printf("\n");
}
void lsdradix_sort(int arr[],int begin,int end,int d)
{
const int radix = 10;
int count[radix],i,j;
int *bucket = (int*)malloc((end - begin+1)*sizeof(int));//所有桶的空间开辟
int k;
//按照分配标准依次进行排序过程
for(k=1;k<=d; ++k)
{
//置空
for(i=0; i<radix; i++)
{
count[i] = 0;
}
//统计各个桶中所有数据个数
for(i=begin; i<=end; i++)
{
count[getdigit(arr[i],k)]++;
}
//count[i]表示第i个桶的右边界索引
for(i=1; i<radix; i++)
{
count[i] = count[i] + count[i-1];
}
//把数据依次装入桶(注意装入时候的分配技巧)
for(i = end; i>=begin; --i) //这里要从右向左扫描,保证排序稳定性
{
j = getdigit(arr[i],k);//求出关键码的第k位的数字,例如:576的第3位是5
bucket[count[j]-1] = arr[i];//放入对应的桶中,count[j]-1是j个桶的右边界索引
--count[j];//对应桶的装入数据索引减一
}
//注意:此时 count[i]为i个桶左边界
// 从各个桶中收集数据
for(i= begin,j=0;i<=end;++i,++j)
{
arr[i] = bucket[j];
}
}
free(bucket);
bucket = NULL;
}
int main()
{
int br[10] = {20,80,90,589,998,985,852,123,456,789};
printf("sort befor:\n");
PrintArr(br,10);
lsdradix_sort(br,0,9,3);
printf("sort after:\n");
PrintArr(br,10);
return 0;
}