建一个临时数组T,长度与待排序数组一样。从数组末尾遍历待排序数组,把元素都安排到T里面,直接从C里面就可以得到元素的具体位置, 不过记得每处理过一个元素之后都要把C里面对应位置的计数减1。
视频:计数排序算法可视化解读
示例代码:我在网上看了巨多代码,但基本都是用来处理 0 以上数的计数排序。下面介绍的这个算法,可以适应小于 0 的数的计数排序,不过我加了很多注释,也很好理解:
public void countSort(int[] arr) { // 找到最大值和最小值 int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; for(int i = 0; i < arr.length; i++){ max = Math.max(max, arr[i]); min = Math.min(min, arr[i]); } int[] b = new int[arr.length]; // 存储数组 int[] count = new int[max - min + 1]; // 计数数组 for (int num = min; num <= max; num++) { // 初始化各元素值为0,数组下标从0开始因此减min count[num - min] = 0; } for (int i = 0; i < arr.length; i++) { int num = arr[i]; count[num - min]++; // 每出现一个值,计数数组对应元素的值+1 // 此时count[i]表示数值等于i的元素的个数 } for (int i = min + 1; i <= max; i++) { count[i - min] += count[i - min - 1]; // 此时count[i]表示数值<=i的元素的个数 // 这样做的目的是为了方便最后赋值, // 「从下个方法的 ‘count[num - min]--’ 可以看出」 } for (int i = 0; i < arr.length; i++) { int num = arr[i]; // 原数组第i位的值 int index = count[num - min] - 1; //加总数组中对应元素的下标 b[index] = num; // 将该值存入存储数组对应下标中 count[num - min]--; // 加总数组中,该值的总和减少1。 } // 将存储数组的值替换给原数组 for(int i=0; i < arr.length;i++){ arr[i] = b[i]; } }桶排序的思想是,首先按特定规则,划分出若干个’桶‘,每个‘桶’有个范围,将大小在对应‘桶’范围内的数,对号入座。再依次将每个‘桶’内的数有序排列,最后按顺序拼接各个‘桶’即可。
步骤:根据待排序集合中最大元素和最小元素的差值范围和映射规则,确定申请的桶个数;
遍历待排序集合,将每一个元素移动到对应的桶中;
对每一个桶中元素进行排序,并移动到已排序集合中。
步骤 3 中提到的已排序集合,和步骤 1、2 中的待排序集合是同一个集合。与计数排序不同,桶排序的步骤 2 完成之后,所有元素都处于桶中,并且对桶中元素排序后,移动元素过程中不再依赖原始集合,所以可以将桶中元素移动回原始集合即可。
视频:桶排序
示例代码:上面讲的计数排序其实一定程度上,也可以看作一种特殊的桶排序,同样的,网上桶排序代码大一堆,啥语言都有。但却没有一个解决小于 0 数排序问题的,要么就不处理要么就抛出异常,下面这个算法,有效的解决了,小于 0 数排序的难题
public static void bucketSort(int[] arr){ // 首先还是找出最大、最小值 int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; for(int i = 0; i < arr.length; i++){ max = Math.max(max, arr[i]); min = Math.min(min, arr[i]); } // 桶数 // 在桶排序中,对桶的划分个数是随意的 // 这个方法划分的桶数量随带划分数列的密集程度改变而改变 int bucketNum = (max - min) / arr.length + 1; ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum); // 初始化各个桶 for(int i = 0; i < bucketNum; i++){ bucketArr.add(new ArrayList<Integer>()); } // 将每个元素放入相应的桶 for(int i = 0; i < arr.length; i++){ int num = (arr[i] - min) / (arr.length); bucketArr.get(num).add(arr[i]); } // 对每个桶进行排序 for(int i = 0; i < bucketArr.size(); i++){ Collections.sort(bucketArr.get(i)); for (int j = 0; j < bucketArr.get(i).size(); j++) { arr[j] = bucketArr.get(i).get(j); } } }