基数排序的若干种方法

单关键字基数排序

步骤:

1.统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
2.对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
3.反向填充目标数组:将每个元素i放在新数组的第C[i]项,每放一个元素就将C[i]减去1.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define num_range (26)

void print_arr(int *arr, int n)
{
	int i;
	for(i=0; i<n; i++)
		printf(!i?"%d":" %d", arr[i]);
	printf("\n");
}
void counting_sort(int *ini_arr, int *sorted_arr, int n)
{
	int *count_arr = (int*)malloc(sizeof(int)*num_range);
	int i, j, k;
	//统计数组中,每个元素出现的次数
	for(k=0; k<num_range; k++) count_arr[k]=0;
	for(i=0; i<n; i++) count_arr[ini_arr[i]]++;
	for(k=1; k<num_range; k++) count_arr[k]+=count_arr[k-1];
	for(j=n-1; j>=0; j--)	/*想一想为什么要反向?*/
	{
		int elem = ini_arr[j];
		int index = count_arr[elem]-1;
		sorted_arr[index] = elem;
		count_arr[elem]--;
	}
	free(count_arr);
}
int main()
{
	int n;
	scanf("%d",&n);
	int i;
	int *arr = (int*)malloc(sizeof(int)*n);
	int *sorted_arr = (int*)malloc(sizeof(int)*n);
	srand(time(0));


	for(i=0; i<n; i++) arr[i] = rand() % num_range;
	printf("ini_array:");
	print_arr(arr,n);
	counting_sort(arr,sorted_arr,n);
	printf("sorted_array:");
	print_arr(sorted_arr,n);
	free(arr);
	free(sorted_arr);
	
	return 0;
}

/*反向,是为了保证相同数值排前面的排名小*/

双关键字基数排序

方法一:

步骤:1.直接将第一关键字放入数组第一维,第二关键字放入数组第二维,该二维数组的值加1;

    2.遍历第一维,再遍历第二维,保证第一关键字升序,若相同时第二关键字升序。a[i][j]=s表示有s对(i , j)。

#include<cstdio>
#include<cstring>
const int maxn = 1000;
const int maxvalue = 2000;
int cnt[maxvalue][maxvalue];

void jishu_sort(int *a, int *b, int n)
{
	//check error///
	if(a==NULL || b==NULL || n<=0) return;
	
	memset(cnt, 0, sizeof(cnt));
	int i, j;
	for(i=1; i<=n; i++)
		cnt[a[i]][b[i]]++;


	for(i=1; i<=maxvalue; i++)
		for(j=1; j<=maxvalue; j++)
		{
			int sum=cnt[i][j];
			while(sum--) printf("%d %d\n", i,j);
		}
}
int main()
{
	int n;
	int a[maxn], b[maxn];
	scanf("%d", &n);
	int i;
	for(i=1; i<=n; i++)
		scanf("%d %d", a+i, b+i);
	jishu_sort(a, b, n);
	return 0;
}
方法二:

步骤:

1.按照单关键字基数排序来将第二关键字排序

2.按照第二关键字的大小顺序来记录相应的第一关键字的位置

3.按照由2.得到的第一关键字顺序来进行基数排序

4.按照第一关键字的大小顺序输出第一关键字和第二关键字

#include<cstdio>
#include<cstring>
const int maxn = 1000;
const int maxvalue = 2000;
void jishu_sort(int *a, int *b, int n)
{
	//检查异常//
	if(a==NULL) {printf("a is NULL\n"); return;}
	if(b==NULL) {printf("b is NULL\n"); return;}
	if(n<=0)	{printf("n<=0\n");return;}
	

	//sa[i]表示排第i的是谁
	int sa[maxn],  //第二关键字中第i大的数的位置
		sa1[maxn]; //第一关键字中第i大的数的位置
	memset(sa,0,sizeof(sa));
	memset(sa1,0,sizeof(sa1));

	int i;
	int cnt[maxvalue];
	//对第二关键字排序
	memset(cnt, 0, sizeof(cnt));
	for(i=1; i<=n; i++)
		cnt[b[i]]++;
	for(i=1; i<=maxvalue; i++)
		cnt[i]+=cnt[i-1];
	for(i=n; i>=1; i--)
		sa[cnt[b[i]]--]=i;
	//对第一关键字排序	
	memset(cnt, 0, sizeof(cnt));
	for(i=1; i<=n; i++)
		cnt[a[sa[i]]]++;
	for(i=1; i<=maxvalue; i++)
		cnt[i]+=cnt[i-1];
	for(i=n; i>=1; i--)
	{
		int rank1=cnt[a[sa[i]]]--;
		sa1[rank1]=sa[i];
	}
	//输出排序后的结果
	for(i=1; i<=n; i++)
		printf("%d %d\n", a[sa1[i]], b[sa1[i]]);
}
int main()
{
	int n;
	scanf("%d", &n);
	int i;
	int a[maxn], b[maxn];//第一,二关键字,值大小不超过maxvalue
	for(i=1; i<=n; i++)
	{
		scanf("%d %d", a+i, b+i);
		if(a[i]<1 || a[i]>maxvalue || b[i]<1 || b[i]>maxvalue)
		{
				printf("数值范围(0~%d)出错,请重新输入\n",maxvalue);
				break;
		}
	}
	//基数排序
	jishu_sort(a, b, n);
	return 0;
}
比较:方法一比较易懂,但是占用空间比较多;

    而方法二在时间和空间上都比较优秀,而且此方法可应用于后缀数组。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值