RadixSort(基数排序)——C语言实现

前言:

基数排序从本质上说就是多关键字排序,根据多关键字进行多次排序以得到总体有序的序列。一大串数字可以看成一个个数字的结合,可以看做一堆关键字,因此对大数字进行排序,基数排序的效率很高,但是问题是会用掉比较多的空间。

思路:

基数排序分为MSD和LSD。LSD,最低位优先,是基数排序。

MSD,最高位优先,是分治法实现的排序,就不是基数排序了。

LSD就是一位一位的排序,先对个位进行排序。再将排序后的数组对十位进行排序······一直实现到最高位,就可以将整体有序。由于要实现到最高位,所以这边我们需要先找到数组中最大的元素,以确定外层循环的次数。(最大数字的位数)

int i, max = a[0], base = 1;
//找到数组最大值,以确定循环次数
for (i = 1; i < length; i++)
	if (a[i] > max)max = a[i];
while (max / base > 0)
{

}

然后其实就是计数排序,不过不用开辟太大的空间了,只需要开辟10个空间对0-9进行排序就可以了。这里有一个位数不相同的问题,但是如果不同的话,整除位数以后是0,排序完是在前面的,并不影响整体的排序,所以没必要进行处理。

如果计数排序不懂得话,理解起来下面的代码可能会有些难度。建议先去看看计数排序的原理

 CountingSort(计数排序

只需要理解到相对应的数据在计数数组中的下标是:bucket[a[i] / base % 10] - 1 就行。

还有一些细节我放在下头的代码中注释了。

排序核心代码:

void RadixSort(int* a, int length)
{
	int i, max = a[0], base = 1;

	//找到数组最大值,以确定循环次数
	for (i = 1; i < length; i++)
		if (a[i] > max)max = a[i];

	int* t = (int*)malloc(sizeof(int) * length);

	while (max / base > 0)
	{
		//默认对数字进行排序
		int bucket[10] = { 0 };

		//计数数组,累加计数数组得到逆序下标
		for (i = 0; i < length; i++)
			bucket[a[i] / base % 10]++;
		for (i = 1; i < 10; i++)
			bucket[i] += bucket[i - 1];

		for (i = length - 1; i >= 0; i--)
		{
			//原始序列中最后一个数据,放在新序列下标为 bucket[a[i] / base % 10] - 1 的地方。
			t[bucket[a[i] / base % 10] - 1] = a[i];  
			bucket[a[i] / base % 10]--;
		}
		//将辅助数组的值复制回原数组,继续下一轮
		for (i = 0; i < length; i++)
			a[i] = t[i];

		//个位->十位->百位->···
		base *= 10;
	}
}

测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 30

//之前写过了,就不再全写一遍了
void generate_random_number(int*, int, int);
void swap(int*, int*);

void RadixSort(int* a, int length)
{
	int i, max = a[0], base = 1;

	//找到数组最大值,以确定循环次数
	for (i = 1; i < length; i++)
		if (a[i] > max)max = a[i];

	int* t = (int*)malloc(sizeof(int) * length);

	while (max / base > 0)
	{
		//默认对数字进行排序
		int bucket[10] = { 0 };

		//计数数组,累加计数数组得到逆序下标
		for (i = 0; i < length; i++)
			bucket[a[i] / base % 10]++;
		for (i = 1; i < 10; i++)
			bucket[i] += bucket[i - 1];

		for (i = length - 1; i >= 0; i--)
		{
			//原始序列中最后一个数据,放在新序列下标为 bucket[a[i] / base % 10] - 1 的地方。
			t[bucket[a[i] / base % 10] - 1] = a[i];  
			bucket[a[i] / base % 10]--;
		}
		//将辅助数组的值复制回原数组,继续下一轮
		for (i = 0; i < length; i++)
			a[i] = t[i];

		//个位->十位->百位->···
		base *= 10;
	}
}

int main()
{
	int arr[N + 10] = { 0 };
	generate_random_number(arr, 0, 1024);

	RadixSort(arr,N);

	printf("排序后数列:\n");
	for (int i = 0; i < N; i++)
		printf("%d ", arr[i]);

	printf("\n");
	return 0;
}

测试结果:

 至此,基数排序完成。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值