【Java 算法】计数排序

计数排序:很强就对了,它的性能比系统API的多线程或单线程排序都快!不过有个前提,就是数据量,不要超过达到 1千万使用计数排序,测试过,性能会比系统API慢,不过也得看数据复杂度对比,一般API并排比计排1千万数据快。

如果max 和 min 只有两个,差值又大,计数排序就很亏,创建的计数数组也就大了

去重版的计数排序很好用

import java.util.Arrays;

public class Main {
	
	public static void main(String[] args) {
		int[] arr1 = {99, 88, -77, -77, 99, -66, 55, 44, 33, -22, 11};
		int[] arr2 = arr1.clone();
		countSort(arr1);
		arr2 = countSort2(arr2);
		System.out.println(Arrays.toString(arr1));
		System.out.println(Arrays.toString(arr2));
	}
	
	// 正常计数排序版本
	public static void countSort(int[] arr) {
		// 打擂台,找到最大与最小值
		int max = arr[0];
		int min = arr[0];
		for (int i = 1; i < arr.length; ++i) {
			if (arr[i] > max) max = arr[i];
			if (arr[i] < min) min = arr[i];
		}
		// 创建一个计数长度数组
		int[] counts = new int[max - min + 1]; // +1 是 max - min 后,得到起本身,也就是 min = 0 时,数组本身从 0 开始,避免这个 bug
		// 计数
		for (int i = 0; i < arr.length; ++i) ++counts[arr[i] - min];
		// 排序
		for (int i = 0, len = 0; i < counts.length; ++i) {
			while (counts[i] > 0) { //当前位置计数的个数,也就是有可能一个数重复
				arr[len++] = min + i; //最小值 + 索引位置 = 精确数
				--counts[i];
			}
		}
	}
	
	// 去重复版计数排序
	public static int[] countSort2(int[] arr) {
		// 打擂台,找到最大与最小值
		int max = arr[0];
		int min = arr[0];
		for (int i = 1; i < arr.length; ++i) {
			if (arr[i] > max) max = arr[i];
			if (arr[i] < min) min = arr[i];
		}
		// 创建一个计数长度数组
		int[] counts = new int[max - min + 1]; // +1 是 max - min 后,得到起本身,也就是 min = 0 时,数组本身从 0 开始,避免这个 bug
		// 计数
		for (int i = 0; i < arr.length; ++i) ++counts[arr[i] - min];
		// 排序 + 去重,也就是把 while 换成 if
		int len = 0;
		for (int i = 0; i < counts.length; ++i) {
			if (counts[i] > 0) { //当前位置有数
				arr[len++] = min + i; //最小值 + 索引位置 = 精确数
				--counts[i];
			}
		}
		// 拷贝数组
		if (len != arr.length) {
			int[] newArr = new int[len];
			System.arraycopy(arr, 0, newArr, 0, len);
			arr = newArr;
		}
		return arr;
	}
	
}

输出:

[-77, -77, -66, -22, 11, 33, 44, 55, 88, 99, 99]
[-77, -66, -22, 11, 33, 44, 55, 88, 99]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

虚妄狼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值