极客时间-排序-计数排序

“计数排序只能用在数据范围不大的场景中,如果数据范围 k 比要排序的数据 n 大很多,就不适合用计数排序了。而且,计数排序只能给非负整数排序,如果要排序的数据是其他类型的,要将其在不改变相对大小的情况下,转化为非负整数。比如,还是拿考生这个例子。如果考生成绩精确到小数后一位,我们就需要将所有的分数都先乘以 10,转化成整数,然后再放到 9010 个桶内。再比如,如果要排序的数据中有负数,数据的范围是[-1000, 1000],那我们就需要先对每个数据都加 1000,转化成非负整数。”

package data.sort.line;

public class CountSort {
	
	
	public static int[] countSort(int b[]) {
		int maxSize=b[0];
		int c[]=new int[b.length];
		//1)找出数据中的最大数
		for(int i=1;i<b.length;i++) {
			if(b[i]>maxSize) {
				maxSize=b[i];
			}
		}	
		
		//确定桶的数量,创建一个maxSize+1的桶数组,桶下标代表数值,桶中存放值代表重复数据的数量
		int bubble[]=new int[maxSize+1];
		//2)把值相等的数据放入到同一个桶中,统计每个桶的数量
		for(int j=0;j<b.length;j++) {
		    bubble[b[j]]++;
		}
		
		//把桶的数组顺序求和,那么这时候每个桶中的值就是包括桶下标在内的小于等于它的数量
		for(int i=1;i<bubble.length;i++) {
			bubble[i]=bubble[i-1]+bubble[i];
		}
		
		/*
		 * 这种方式会多执行很多次,自己手写第一遍就是这样实现的,这样bubble中的值会被当作
		 * bubble下标值重复的次数,最后也能得到正确的结果
		*/
		/*for(int k=bubble.length-1;k>=0;k--) {
			while(bubble[k]>0) {
				c[bubble[k]-1]=k;
				bubble[k]--;
			}
		}*/
		
		//正确实现  从后向前循环,目的是为了保证稳定性  
        //如原本数组中2   2   2   是在0 1 2的位置 经过上述步骤得到bubble 0  1  3
//第一个2应该是 bubble[2]也就是3 被放在了下标是2的c中,但是原本在的位置是0
		for(int i=b.length-1;i>=0;i--) {
			int realIndex=--bubble[b[i]];//值在正确排序数组中的位置
			c[realIndex]=b[i];
		}
		
		return c;
	}
	
	
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//计数排序:
		//1)找出数据中的最大数,确定桶的数量,创建一个maxSize+1的桶数组
		//2)把值相等的数据放入到同一个桶中,统计每个桶中的数量(桶下标代表数值,桶中存放值代表重复数据的数量)
		//3)把桶的数组顺序求和,那么这时候每个桶中的值就是包括自己在内的小于等于它的个数
		//4)从后向前依次循环数组,桶中存储的值就是桶下标值应该在的正确位置(第几个),每次循环减去1得到得就是b[i]应该在c中的位置
		int a[]= {3,4,2,1,4,4};
		a=CountSort.countSort(a);
		for(int i=0;i<a.length;i++) {
			System.out.println(a[i]);
		}

	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值