基数排序的详解

目录

计数排序

基数排序      

总结 

计数排序

       计数排序是对存在有限较短的情况的数组进行排序,可以将数组中每一个数出现的频率进行统计,从而达到排序。

public static void countSort(int[] arr) {
	if (arr == null || arr.length < 2) {
		return;
	}//如果数组为空或者数组的长度为1,直接返回
	int max = Integer.MIN_VALUE;
	for (int i = 0; i < arr.length; i++) {
		max = Math.max(max, arr[i]);
	}//求出数组中的最大值
	int[] bucket = new int[max + 1];//建立一个长度为最大值加1的辅助数组
	for (int i = 0; i < arr.length; i++) {
		bucket[arr[i]]++;
	}//对数组中每一个数出现的频率进行统计
	int i = 0;
	for (int j = 0; j < bucket.length; j++) {
		while (bucket[j]-- > 0) {
			arr[i++] = j;//按照关键词的位序依次输出排好序的数,放到原数组
		}
	}
}

      上面代码的时间复杂度为O\left ( N \right ),对于情况较少的数组排序比较快,但是对于情况较多的排序,时间复杂度较高,根据情况进行选择。

基数排序      

       基数排序是一种很特别的排序方法,它不基于比较和移动进行排序,而是基于关键词各位的大小进行排序。例如对于一串数字,100,28,89,46,128,首先找到最大的数字,将他的位数作为最终的位数,其它位数不够的数字前面补0。然后将所有的数字分别按照个位数,十位数,百位数从小到大排列,最终的数组就是排好序的数组。

       代码的实现对操作进行了一定的优化,代码如下:

public static void radixSort(int[] arr) {
	if (arr == null || arr.length < 2) {
		return;//如果数组为空或者数组的长度为1,直接返回
	}
	radixSort(arr, 0, arr.length - 1, maxbits(arr));//maxbits(arr)表示数组中最大值的位数
}

public static int maxbits(int[] arr) {//求出数组中最大值的位数
	int max = Integer.MIN_VALUE;
	for (int i = 0; i < arr.length; i++) {
		max = Math.max(max, arr[i]);
	}
	int res = 0;
	while (max != 0) {
		res++;
		max /= 10;
	}
	return res;
}

public static void radixSort(int[] arr, int begin, int end, int digit) {
	final int radix = 10;//每一位最多有十个不同的数字,以10为基底
	int i = 0, j = 0;

	int[] bucket = new int[end - begin + 1];//准备一个辅助数组和原数组长度相同
	for (int d = 1; d <= digit; d++) {//有多少位就进出几次
		int[] count = new int[radix];//10个空间
		for (i = begin; i <= end; i++) {//从数组的开始位置开始到结束位置,依次提取数组中每一个数的相应位数的数值
		    j = getDigit(arr[i], d);//提取数组中数的第d位的数
			count[j]++;//数字为j的数量加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);
			bucket[count[j] - 1] = arr[i];
			count[j]--;
		}//对于原始数组从end位置开始往回,对每一个数,从个位数开始,进行排序,根据数字找到相应的数字频数-1的对应辅助数组的位置就是对应的位置
		for (i = begin, j = 0; i <= end; i++, j++) {
			arr[i] = bucket[j];//上述循环完毕将辅助数组排好序的数字复制回原数组
		}
	}
}

public static int getDigit(int x, int d) {
	return ((x / ((int) Math.pow(10, d - 1))) % 10);
}//提取一个数字d位的数字

       上面程序的时间复杂度为O\left ( N \right ),空间复杂度为O\left ( M \right )(M表示根据关键词的情况对空间进行调用)。

总结 

       对于这种不基于比较和移动的排序,一定要根据具体的排序情况和特征对排序的程序进行编写,没有普遍适用的,而其中最重要的排序就是基数排序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值