桶排序算法
桶排序的两个关键点:
- 如何让需要排序的数组中的数值更加平均的分配到桶里。
- 如何让桶里的数据进行排序。
桶排序的两种模式
- 桶的数量大于等于需要排序的数组中的最大值,这样的话可以直接忽略上面两个关键点,只适合于小取值范围的排序,见simpleBucketSort。
- 桶的数量不等于数组中的最大值。需要定义数值分配到桶的算法以及桶内排序的算法。见bucketSort
package com.miracle.study.sort;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* @author Miracle
* @date 2021/4/7 12:40
*/
public class BucketSort {
/**
* 使用条件:桶的数量必须大于等于需要排序的值的最大取值。
* @param sortData 需要排序的数组
* @return
*/
public List<Integer> simpleBucketSort(List<Integer> sortData){
// 创建桶
var k = 20;
var buckets = new ArrayList<LinkedList<Integer>>(k);
for (int i = 0; i < k; i++){
buckets.add(new LinkedList<>());
}
// 将数据添加到桶
for (var data : sortData){
buckets.get(data % k).add(data);
}
// 将数据提取出来
var list = new ArrayList<Integer>();
for (var bucket : buckets){
list.addAll(bucket);
}
return list;
}
/**
* 通用桶算法
* @param sortData 需要排序的数组
* @param k 桶数量
* @param max 排序的数组中最大的值
* @param min 排序的数组中最小的值
* @return
*/
public List<Integer> bucketSort(List<Integer> sortData, int k, int max, int min){
// 创建桶
var buckets = new ArrayList<LinkedList<Integer>>(k);
for (int i = 0; i < k; i++){
buckets.add(new LinkedList<>());
}
// 将数据添加到桶
for (var data : sortData){
// 最大值到最小值的数值差,+1表示加上自身
var sortValue = max - min + 1;
// 计算桶的位置(其他算法也可以,选择能够让取值更平均分配到桶类即可)
// 最小值到取值与范围的百分比乘k
var key = (data - min) * k / sortValue;
buckets.get(key).add(data);
}
// 将数据提取出来
var list = new ArrayList<Integer>();
var quickSort = new QuickSort();
for (var bucket : buckets){
// 对桶内的数据进行快速排序,这里的算法也可替换
list.addAll(quickSort.simpleQuickSort(bucket));
}
return list;
}
@Test
public void test(){
// List<Integer> integers = simpleBucketSort(Arrays.asList(1, 15, 5, 7, 16, 9, 12, 3, 6, 8, 18, 4, 2, 10, 0, 19));
// integers.stream().forEach(e -> System.out.println(e));
List<Integer> integers = bucketSort(Arrays.asList(1, 15, 5, 7, 16, 9, 12, 3, 6, 8, 18, 4, 2, 10, 0, 19),10,19,1);
integers.stream().forEach(e -> System.out.println(e));
}
}