今日内容
1、桶排序 2、计数排序 3、基数排序
这些排序算法的时间复杂度是线性的(原因是这三个算法是非基于比较的排序算法,都不涉及元素之间的比较操作。),所以我们把这类排序算法叫作线性排序(Linear sort)
这三种排序算法的时间复杂度是 O(n)
一、桶排序(Bucket sort)
1、分桶的时候,应该怎么分?分几个?每个范围是多少?
2、放入桶的时候,应该怎么查找放入哪一个桶?
1、核心思想
在一个数组中找到最大值和最小值,然后根据最大值和最小值、数组长度得出桶的个数和每个桶的范围。(有序的桶)然后遍历整个数组每个元素,去对比在哪个桶内?并且放入对应桶中,最后把每个桶单独排序,把每个桶连起来后就是有序的了。
2、代码实现
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
/**
* 桶排序
*/
public class BucketSort {
public static void main(String[] args) {
double[] arr = {
1.2,2.5,9.5,1.3,1.1};
double[] doubles = bucketSort(arr);
System.out.println(Arrays.toString(doubles));
}
public static double[] bucketSort(double[] array){
//得到数列的最大值和最小值,并计算出差值d
double max=array[0];
double min=array[0];
for (int i=1;i<array.length;i++){
if (array[i]>max){
max=array[i];
}
if (array[i]<min){
min=array[i];
}
}
double d=max-min;
//初始化桶 初始化一个集合(集合类型是集合)设置长度为原数组的大小
int bucketNum=array.length;//求桶的个数(和每个桶的范围)公式不是唯一,只要尽量将数据均匀分布即可。
// int bucketNum = (max - min) / arr.length + 1;
ArrayList<LinkedList<Double>> bucketList=new ArrayList<LinkedList<Double>>(bucketNum);
for (int i=0;i<bucketNum;i++){
//添加满集合
bucketList.add(new LinkedList<Double>());
}
//遍历原始数组将每个元素放入桶中
for (int i=0;i<array.length;i++){
//桶的编号(索引):当前值与最小值之间的差值。d:最大最小值的差值
int num=(int)((array[i]-min)*(bucketNum-1)/d);
// int num = (arr[i] - min) / (arr.length);
//得到对应索引位置的桶(集合类型),然后将当前值添加到该桶。
bucketList.get(num).add(array[i]);
}
//对每个桶内部进行排序
for(int i=0;i<bucketList.size();i++){
// 使用Collections.sort,其底层实现基于归并排序或归并排序的优化版本
Collections.sort(bucketList.get(i));
}
//输出全部元素
double[] sortedArray=new double[array.length];
int index=0;
for (LinkedList<Double> list:bucketList) {
for (double element:list){
sortedArray[index]=element;
index++;
}
}
return sortedArray;
}
}
3、应用场景(桶排序比较适合用在外部排序中)
比如说我们有 10GB 的订单数据,我们希望按订单金额(假设金额都是正整数)进行排序,但是我们的内存有限,只有几百 MB,没办法一次性把 10GB 的数据都加载到内存中。这个时候该怎么