桶排序
算法描述:

桶排序的思想近乎彻底的分治思想。假设现在需要对一百个数进行排序。我们可以将其等长地分到10个虚拟的“桶”里面,这样,平均每个桶只有10个数。如果每个桶都有序了,则只需要依次输出为有序序列即可。具体思路是这样的:
1.将待排数据按一个映射函数f(x)分为连续的若干段。理论上最佳的分段方法应该使数据平均分布;实际上,通常采用的方法都做不到这一点。显然,对于一个已知输入范围在【0,100】的数组,最简单的分段方法莫过于x/m这种方法,例如,f(x)=x/10。“连续的”这个条件非常重要,它是后面数据按顺序输出的理论保证。
2.分配足够的桶,按照f(x)从数组起始处向后扫描,并把数据放到合适的桶中。对于上面的例子,如果数据有100个,则我们需要分配10个桶,理想情况下,每个桶有大约10个数据。
3.对每个桶进行内部排序,例如,使用插入排序、快速排序等。注意,如果数据足够大,这里可以继续递归使用桶排序,直到数据大小降到合适的范围。
4.按顺序从每个桶输出数据。例如,1号桶【3,9】,2号桶没有,3号桶【21,25, 29】,4号桶【37】,5号桶【43, 49】则输出序列为【3,9,21,25,29,37,43,49】。
5.排序完成。
时间复杂度:最优情况O(n)
空间复杂度:O(m+n)
java实现:
public static void bucketSort(int[] arr) {
// 分桶,这里采用映射函数f(x)=x/10。
// 输入数据为0~99之间的数字
int bucketCount = 10;
Integer[][] bucket = new Integer[bucketCount][arr.length]; // Integer初始为null,以与数字0区别。
for (int i = 0; i < arr.length; i++) {
int quotient = arr[i] / 10; // 这里即是使用f(x)
for (int j = 0; j < arr.length; j++) {
if (bucket[quotient][j] == null) {
bucket[quotient][j] = arr[i];
break;
}
}
}
// 小桶排序
for (int i = 0; i < bucket.length; i++) {
// 小桶用插入排序,也可以继续递归用桶排序
for (int j = 1; j < bucket[i].length; ++j) {
if (bucket[i][j] == null) {
break;
}
int value = bucket[i][j];
int position = j;
while (position > 0 && bucket[i][position - 1] > value) {
bucket[i][position] = bucket[i][position - 1];
position--;
}
bucket[i][position] = value;
}
}
// 输出
for (int i = 0, index = 0; i < bucket.length; i++) {
for (int j = 0; j < bucket[i].length; j++) {
if (bucket[i][j] != null) {
arr[index] = bucket[i][j];
index++;
} else {
break;
}
}
}
}GitHub地址:
https://github.com/xckNull/Algorithms-introduction.git
本文介绍了一种基于分治思想的桶排序算法,该算法通过将数据分到多个虚拟的“桶”内,再分别对每个桶内的数据进行排序,最后依次输出所有桶中的数据来达到排序的目的。适用于数据范围已知的情况。
663

被折叠的 条评论
为什么被折叠?



