桶排序是一种排序技术,它通过首先将元素分成几个称为桶的组来对元素进行排序。使用合适的排序算法或递归调用同一算法对每个存储桶中的元素进行排序。
创建了几个存储桶。每个存储桶都填充有特定范围的元素。使用任何其他算法对存储桶中的元素进行排序。最后,收集存储桶中的元素以获取排序后的数组。
桶排序的过程可以理解为分散收集方法。首先将元素分散到存储桶中,然后对存储桶的元素进行排序。最后,元素按顺序收集。
桶排序工作
桶排序如何工作?
- 假设输入数组为:
输入数组
创建一个大小为10的数组。此数组的每个插槽都用作存储元素的存储桶。每个位置是一个存储桶的数组
- 将元素插入数组中的存储桶。根据铲斗的范围插入元素。
在我们的示例代码中,我们具有范围从0到1、1到2、2到3,...(n-1)到n的存储桶。
假设采用了输入元素.23
。它乘以size = 10
(即.23*10=2.3
)。然后,将其转换为整数(即2.3≈2
)。最后,将.23插入bucket-2中。将元素从数组插入存储桶
同样,.25也插入同一存储桶中。每次都采用浮点数的下限值。
如果我们使用整数作为输入,则必须将其除以间隔(此处为10)以获取下限值。
同样,其他元素也会插入各自的存储桶中。将所有元素插入数组中的存储桶
- 使用任何稳定的排序算法对每个存储桶的元素进行排序。在这里,我们使用了quicksort(内置函数)。
对每个存储桶中的元素进行排序
- 收集每个存储桶中的元素。
通过遍历存储桶并在每个循环中将单个元素插入原始数组来完成此操作。一旦将存储桶中的元素复制到原始数组中,该元素将被擦除。收集每个存储桶中的元素
桶分类算法
bucketSort()
创建N个存储桶,每个存储桶可以容纳一定范围的值
对于所有的水桶
使用0值初始化每个存储桶
对于所有的水桶
将元素放入符合范围的存储桶中
对于所有的水桶
对每个存储桶中的元素进行排序
从每个桶中收集元素
端斗排序
Java示例
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class BucketSortDemo {
/**
* Bucket sort
*
* @param array array to be sorted
* @param bucketCount number of buckets
* @return array sorted in ascending order
*/
public static int[] bucketSort(int[] array, int bucketCount) {
if (bucketCount <= 0)
throw new IllegalArgumentException("Invalid bucket count");
if (array.length <= 1)
return array; // trivially sorted
int high = array[0];
int low = array[0];
for (int i = 1; i < array.length; i++) { // find the range of input elements
if (array[i] > high)
high = array[i];
if (array[i] < low)
low = array[i];
}
double interval = ((double) (high - low + 1)) / bucketCount; // range of one bucket
ArrayList<Integer> buckets[] = new ArrayList[bucketCount];
for (int i = 0; i < bucketCount; i++) { // initialize buckets
buckets[i] = new ArrayList<Integer>();
}
System.out.println(Arrays.toString(buckets));
for (int i = 0; i < array.length; i++) { // partition the input array
buckets[(int) ((array[i] - low) / interval)].add(array[i]);
}
System.out.println(Arrays.toString(buckets));
int pointer = 0;
for (int i = 0; i < buckets.length; i++) {
Collections.sort(buckets[i]); // mergeSort
System.out.println(Arrays.toString(buckets));
for (int j = 0; j < buckets[i].size(); j++) { // merge the buckets
array[pointer] = buckets[i].get(j);
pointer++;
}
}
return array;
}
public static void main(String[] args) {
int[] arr = { 11, 9, 21, 8, 17, 19, 13, 1,24,12 };
System.out.println("未排序:" + Arrays.toString(arr));
bucketSort(arr, 5);
System.out.println("排序后:" + Arrays.toString(arr));
}
}
输出:
未排序:[11, 9, 21, 8, 17, 19, 13, 1, 24, 12]
[[], [], [], [], []]
[[1], [9, 8], [11, 13, 12], [17, 19], [21, 24]]
[[1], [9, 8], [11, 13, 12], [17, 19], [21, 24]]
[[1], [8, 9], [11, 13, 12], [17, 19], [21, 24]]
[[1], [8, 9], [11, 12, 13], [17, 19], [21, 24]]
[[1], [8, 9], [11, 12, 13], [17, 19], [21, 24]]
[[1], [8, 9], [11, 12, 13], [17, 19], [21, 24]]
排序后:[1, 8, 9, 11, 12, 13, 17, 19, 21, 24]
复杂
- 最坏情况的复杂性: 当数组中有近距离的元素时,它们很可能放在同一存储桶中。这可能会导致某些存储桶中的存储元素数量比其他存储桶更多。 它使复杂度取决于用于对存储桶元素进行排序的排序算法。 当元素按相反顺序排列时,复杂性将变得更糟。如果使用插入排序对存储桶中的元素进行排序,则时间复杂度变为。
O(n2)
O(n2)
- 最佳情况复杂度:
O(n+k)
当元素在存储桶中均匀分布且每个存储桶中元素数量几乎相等时,会发生这种情况。
如果存储桶中的元素已经被排序,那么复杂性就会变得更好。
如果使用插入排序对存储桶中的元素进行排序,则最佳情况下的总体复杂度将是线性的。O(n+k)
。O(n)
是制造水桶O(k)
的复杂度,是使用在最佳情况下具有线性时间复杂度的算法对水桶的元素进行分类的复杂度。 - 平均情况复杂度:
O(n)
当元素在数组中随机分布时,会发生这种情况。即使元素分布不均匀,存储桶排序也会在线性时间内运行。直到铲斗尺寸的平方和在元素总数中呈线性关系时,它才成立。
桶分类应用
在以下情况下使用存储桶排序:
- 输入在一个范围内均匀分布。
- 有浮点值