一)算法介绍
桶排序也可称为箱排序,是计数排序的升级版。
工作原理:把数据平均分布到有限数量的桶中,再对每一个桶中的数据分别排序(对桶中数据排序是可选的,看具体情况)。
优势:它利用了函数的映射关系,减少了数据的比较操作,效率取决于映射函数。
二)算法原理
基本原理:
第一步:声明有限数量的桶,如:纯数字可以申请10个桶,纯字母可以申请26个桶。桶的数量是自定义,主要是方便计算。
第二步:编写一个映射函数,把数据一个个均匀分配到每个桶中。
第三步:由于数据会有大小的差异,所以需要分别对每个桶的数据再进行排序(排序方式可自选)。
第四步:把已排好序的数据从桶中一个个复制到源数据中。
备注:对桶中的数据排序操作,(第三步)不一定是必须的。如只统计每个桶中数量的情况下。
例如:统计全国高考每一科目,分数在0到150分,分别各有多少人,假设不存在小数的情况,只需要声明151个桶,把数据均匀分配到每一个桶中,再计算每个桶中的数量,即可得出结果。
算法步骤图解:
源数据:double[] nums = {44.12, 34.12, 45.99, 23.65, 34.05, 98.99, 45.33, 12.43, 98.67, 11.66};
第一步、由于数字只有0到9共10个数,申请10个桶。
第二步、根据映射函数计算元素需要分配到那一个桶中。计算方式:int index = ((int)data)%10;
第三步、数据有大小差异,在分配到桶中的时候,需要再对桶中的数据进行排序(如插入排序)。
第四步、把已排好序的数据复制到源数据中,完成排序。
算法排序效果图:
算法复杂度:
最差情况:T(n) = O(n^2)
最好情况:T(n) = O(n+k)
// O(n^2)含义
for(i=0;i<100;i++) {
for(i=0;i<100;i++){
}
}
三)算法源码
步骤简介:先声明有限数量个桶,按照映射函数把数据一个个均匀分配到每一个桶中,再对每一个桶中数据进行插入排序,最后把已排好序的数据重新复制到源数据中。
/**
* 桶排序
* @param nums
* @return
*/
public static double[] bucketSort(double[] nums) {
if (nums == null) {
return null;
}
// 由于数字只有0到9总共10个数字,所以声明10个桶
ArrayList<LinkedList<Double>> buckets = new ArrayList<LinkedList<Double>>();
for (int i=0; i<10; i++) {
buckets.add(new LinkedList<Double>());
}
for (double data : nums) {
int index = ((int)data)%10; // 映射函数
insertionSort(buckets.get(index), data); // 每一个桶的元素排列可能不一直,需要单独对桶中的元素再进行排序
}
// 把已排好序的数据复制到源数据中
int index = 0;
for (LinkedList<Double> bucket : buckets) {
for (double data : bucket) {
nums[index++] = data;
}
}
return nums;
}
/**
* 插入排序
* @param bucket
* @param data
*/
public static void insertionSort(LinkedList<Double> bucket, double data) {
ListIterator<Double> iterator = bucket.listIterator();
boolean flag = true; // 标识是否已经排序
while (iterator.hasNext()) {
if(data <= iterator.next()) {
iterator.previous(); // 上移一个位置
iterator.add(data);
flag = false;
break;
}
}
if(flag) {
bucket.add(data);
}
}
识别二维码关注个人微信公众号
本章完结,待续,欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!