基数排序和计数排序

本文介绍了几种非比较排序算法,包括基数排序、计数排序和桶排序的基本原理及实现过程。详细探讨了这些算法的时间复杂度和应用场景,并通过具体代码示例展示了如何使用这些算法进行数据排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基数排序,计数排序是常用的几种非比较排序,之前涉及到的排序方式基本都是基于比较的,复杂度最优的情况是O(nlogn),而非比较排序可以实现线性时间完成排序。但是相应的空间复杂度会有所增加。

桶排序(计数排序) :对于序列中的每一个元素,计算得到小于该元素的元素个数,从而确定了该元素在最终输出元素的位置。计数排序有一个非常重要的地方就是:假定数据的范围是在某个区间内,如果数据的大小相差非常大的话,那么计数排序是不适用的。比如三个数1,11111111,222222222222,那么在计数排序中开辟的空间消耗和时间消耗是非常不值得的。

代码如下:

public class BucketSort{
	public static void buckerSort(int []arr){
		if (arr==null||arr.length==0) {
			return ;
		}
		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];
		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;
			}
		}
	}
}

基数排序比较复杂,基数排序最初是用在打孔卡片制表机上的一种排序算法,由Herman Hollerith发明,也就是IBM的创始人。基数排序从最低为开始来排序的,从低位到高位,按位排序,按位排序必须是稳定的。

代码:

class RadixSort{
	public static void radixSort(int []arr){
		if (arr==null||arr.length==0) {
			return ;
		}
		radixSort(arr,0,arr.length-1,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){
		//定义好基数为10
		final int radix=10;
		int i=0,j=0;
		int []count=new int[radix];
		int []bucket=new int [end-begin+1];
		for (int d=1; d<=digit; d++) {
			//对数字的每一位做排序
			for (i=0; i<radix; i++) {
				count[i]++;
			}
			for (i=begin; i<end; i++) {
				j=getDigit(arr[i],d);
				count[j]++;
			}
			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--];
			}
			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);
	}
}

计数排序的一种应用:求数组排序后相邻两个数的最大差值。这里将数字放入桶中,以大于0,小于100的数为例。我们可以根据题目需要分出10个桶,第一个桶放0~9范围内的数,第二个10~19范围内的数,......依次类推。同一个桶内的数字之差一定小于两个桶之间的差。那么又因为数组是经过排序的。所以最大差值一定出现在(前一个桶的最大值与其之后的桶的最小值之差)之间。我们用一个大小为10个数组存这些值之间的差。然后找出最大值即可。

public class MaxGap {
	public static int maxGap(int []nums){
		if (nums==null||nums.length<2) {
			return 0;
		}
		int len=nums.length;
		int min=Integer.MAX_VALUE;
		int max=Integer.MIN_VALUE;
		for (int i = 0; i < len; i++) {
			//求出数组中的最大值与最小值。
			min=Math.min(min, nums[i]);
			max=Math.max(max, nums[i]);
		}
		if (max==min) {
			return 0;
		}
		//默认为false
		boolean hasNum[]=new boolean[len+1];
		int []maxs=new int [len+1];
		int []mins=new int [len+1];
		int bid=0;
		for (int i = 0; i < len; i++) {
			//得出同一个桶内的最大值最小值即可
			bid=bucket(nums[i],len,min,max);
			maxs[bid]=hasNum[bid]?Math.max(maxs[bid], nums[i]):nums[i];
			mins[bid]=hasNum[bid]?Math.min(mins[bid], nums[i]):nums[i];
		}
		int res=0;
		int lastMax=maxs[0];
		int i=1;
		//最大差值是前一个桶的最大值与当前桶的最小值之间的差
		for (; i < len; i++) {
			if (hasNum[i]) {
				res=Math.max(res, mins[i]-lastMax);
				lastMax=maxs[i];
			}
		}
		return res;	
	}
	//根据值大小判断存储的位置
	private static int bucket(long num, long len, long min, long max) {
		return (int) ((num-min)*len/(max-min));
	}
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值