简单介绍
桶排序过程中存在两个关键环节
算法过程:划分多个范围相同的区间,每个自区间自排序,最后合并
图解过程
算法分析
O(k) > O(nlog(n))
的时候其效率反而不如基于比较的排序 // 基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序public static void bucketSort(int[] arr) {
// 1. 确定数据的范围
int max = arr[0];
int min = arr[1];
for(int i = 1; i < arr.length; i++) {
max = Math.max(max, arr[i]);
min = Math.min(min, arr[i]);
}
// 2. 计算桶的个数, 划分桶
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>());
// 3. 将元素放入桶中
for(int i = 0; i < arr.length; i++) {
int num = (arr[i] - min) / arr.length;
bucketArr.get(num).add(arr[i]);
}
// 4. 桶内排序
for(int i = 0; i < bucketArr.size(); i++) {
Collections.sort(bucketArr.get(i));
System.out.println(bucketArr.get(i));
}
// 5. 将桶中元素赋值到原序列
for(int i = 0, index = 0; i < bucketArr.size(); i++)
for(int j = 0; j < bucketArr.get(i).size(); j++)
arr[index++] = bucketArr.get(i).get(j);
}
public class CountingSort {
public static void main(String[] args) {
// int[] arr1 = {9, 3, 5, 4, 9, 1, 2, 7, 8, 1, 3, 6, 5, 3, 4, 0, 10, 9, 7, 9};
int[] arr23 = new int[200];
for(int i = 0; i < arr23.length; i++)
arr23[i] = (int) (Math.random()*50) + 150;
System.out.println("原始数组:");
print(arr23);
int[] result = sort_3(arr23);
System.out.println("结果数组:");
print(result);
}
// 解决稳定性问题:① 计数数组 → 累加数组 ② 反向遍历原始数组
public static int[] sort_3(int[] arr) { // O(n+k)
// 找最大值 和 最小值
int max = arr[0];
int min = arr[0];
for(int i = 1; i < arr.length; i++) { // O(n)
if(max < arr[i]) max = arr[i];
if(min > arr[i]) min = arr[i];
}
// 计数数组 {3, 5, 2}
int[] count = new int[max-min+1];
for(int i = 0; i < arr.length; i++) // O(n)
count[arr[i]-min]++;
// 计数数组 → 累加数组 {3, 8, 10}
for(int i = 1; i < count.length; i++) // O(k)
count[i] = count[i] + count[i-1];
// 利用[累加数组]对原始数组{0101212011}反向遍历生成结果数组
int[] result = new int[arr.length];
for(int i = arr.length-1; i >= 0; i--) // O(n)
result[--count[arr[i]-min]] = arr[i];
return result;
}
// 局限性:不稳定
public static int[] sort_2(int[] arr) { // O(n+k)
// 找最大值 和 最小值
int max = arr[0];
int min = arr[0];
for(int i = 1; i < arr.length; i++) { // O(n)
if(max < arr[i]) max = arr[i];
if(min > arr[i]) min = arr[i];
}
// 计数数组
int[] count = new int[max - min + 1];
for(int i = 0; i < arr.length; i++)
count[arr[i]-min]++;
// 组织结果数组
int[] result = new int[arr.length];
for(int i = 0, index = 0; i < count.length; i++) // O(k)
while(count[i]-- > 0)
result[index++] = i + min;
return result;
}
// 局限性:① 数据起始范围必须从0开始, 不然就会有空间浪费 ② 不稳定
public static int[] sort_1(int[] arr) {
// 找最大值
int max = arr[0];
for(int i = 1; i < arr.length; i++)
if(max < arr[i]) max = arr[i];
// 计数数组(0也是数据噻, 所以要+1)
int[] count = new int[max + 1];
for(int i = 0; i < arr.length; i++)
count[arr[i]]++;
// 组织结果数组
int[] result = new int[arr.length];
for(int i = 0, index = 0; i < count.length; i++)
while(count[i]-- > 0)
result[index++] = i;
return result;
}
public static void print(int[] arr) {
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}
原文:https://www.cnblogs.com/liujiaqi1101/p/12605380.html