一篇文章弄懂——桶排序
概述
上一篇我们学习了堆排序,今天我们来研究一下桶排序,桶排序的思想中也是将排序问题小型化,然后达到排序的目的。在我看来桶排序就是对插入排序的一种优化。
桶排序的思路
相比与生涩难懂的代码,图解的方式来描述问题是一个非常好的方法,直观的图片永远会比抽象的代码更容易理解。话不多说直接上图:
我们给出一个长度为10的待排序数组,以及4个桶:
我们分别给4个桶编号:
我们规定:0号桶中放0~24的值,1号桶放25~49的值,2号桶放50~74的值,3号桶放75~100的值。
现在我们将待排序数组中的值依次放入桶中,但是一定要保证每个桶中元素的顺序(入桶时使用插入排序):
经过N步后,所有元素都入桶了:
当所有元素都入桶后,按照顺序出桶,即可完成排序:
经过N步后,全部元素出桶即完成排序:
思路总结
如果用一句话总结桶排序:通过“分配”和“收集”的过程完成桶排序。
桶排序的中心思想是:设计K个桶,然后将N个桶分散到K个桶中,将每个桶进行排序,然后按照次序将各个桶中元素输出即可完成排序操作。
桶排序实际上就是将插入排序的问题小型化,是一种以空间换时间的典型案例。假如桶的数量等于待排序数组的元素个数,那么分摊到每个桶中的元素就只有一个(需要配合优秀的Hash算法),那么就不存在每个桶的排序的问题,那么此时就使得桶排序的时间效率达到最优。
桶排序的实现
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr = {7, 5, 12, 6, 24, 41, 1, 31, 50,54};
bucketSort(arr);
System.out.println(Arrays.toString(arr));
}
private static class Node {
int value;
Node next;
public Node(int value) {
this.value = value;
}
}
/**
* 桶排序
* @param arr
*/
private static void bucketSort(int[] arr) {
int bucketNum = arr.length / 4 + 1;//桶的个数
Node[] buckets = new Node[bucketNum];
int max = max(arr);
for (int value : arr) {
int index = hashIndex(value, bucketNum, max);//计算桶的位置
pushValue(buckets, index, value);//将值入桶
}
//顺序出桶
int current = 0;
for (int i = 0; i < buckets.length; i++) {
Node root = buckets[i];
while (root != null) {
arr[current] = root.value;
root = root.next;
current++;
}
}
}
/**
* 计算指定值的桶编号
*
* @param value 需要映射的值
* @param bucketNum 数组长度(桶的个数)
* @param valueMax 待排序数组中的最大值
* @return
*/
private static int hashIndex(int value, int bucketNum, int valueMax) {
return value / (valueMax + 1) * bucketNum;
}
/**
* 获得给定数组中的最大值
*
* @param arr
* @return
*/
private static int max(int[] arr) {
int max = Integer.MIN_VALUE;
for (int i : arr) {
if (i > max) {
max = i;
}
}
return max;
}
private static void pushValue(Node[] buckets, int index, int value) {
Node root = buckets[index];
if (root == null) {
buckets[index] = new Node(value);
} else {
Node current = root;
if (root.value >= value) {
Node next = root;
Node node = new Node(value);
buckets[index] = node;
node.next = next;
return;
}
while (current != null) {
if (current.next == null) {
current.next = new Node(value);
return;
} else if (current.next.value >= value) {
Node next = current.next;
Node node = new Node(value);
current.next = node;
node.next = next;
return;
} else {
current = current.next;
}
}
}
}
}
原创不易,各位看官点个赞呗!!!