如果要对大量的一定范围内的数据进行排序,比如100000个0-99的数字进行排序,可以使用桶排序。
在设置了桶个数对应数字范围的情况下,时间复杂度O(N)
代码:
public List<Integer> sort(List<Integer> A) {
int k = 100;
ArrayList<LinkedList<Integer>> buckets = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < k; i++) {
buckets.add(new LinkedList<>());
}
for (int item : A) {
buckets.get(item % k).add(item);
}
for (LinkedList<Integer> bucket : buckets) {
list.addAll(bucket);
}
return list;
}
测试代码
@Test
public void testBucketSort() {
List<Integer> A = gen(100000);
long startTime = System.currentTimeMillis();
BucketSort bucketSort = new BucketSort();
A = bucketSort.sort(A);
assertSorted(A);
System.out.println("Time: " + (System.currentTimeMillis() - startTime));
}
private List<Integer> gen(int n) {
List<Integer> list = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
list.add((int) (Math.random() * 100));
}
return list;
}
private void assertSorted(List<Integer> A) {
Integer o = Integer.MIN_VALUE;
for (int i : A) {
if (o > i) {
Assert.fail("Array not in sorted order");
}
o = i;
}
}
结果
Time: 27
Process finished with exit code 0
使用归并排序时间=108
使用选择排序时间=1967
更通用的代码
多一个步骤:对桶内元素进行排序
public List<Integer> sort(List<Integer> A, int k, int max, int min) {
ArrayList<LinkedList<Integer>> buckets = new ArrayList<>();
ArrayList<Integer> ret = new ArrayList<>();
// min 到 max 之间的长度
int D = max - min + 1;
QuickSort quicksort = new QuickSort();
// 初始化所有的桶
for (int i = 0; i < k; i++) {
buckets.add(new LinkedList<>());
}
// 把元素放到桶里
for (int item : A) {
// 计算的是 item 对应的是哪个桶
int key = (item - min) * k / D;
buckets.get(key).add(item);
}
// 将桶里的值排序后放回到结果集中
for (int i = 0; i < k; i++) {
ret.addAll(quicksort.sortList(buckets.get(i)));
}
return ret;
}