1. 问题描述:使用桶排序算法对控制台输入的数字进行排序
2. 桶排序涉及到几个问题:
① 桶的大小,这里我们可以根据输入的元素的个数来确定桶的大小
② 怎么样确定当前元素进入哪一个桶,这里我们使用到的是通过一个哈希函数来进行计算
int index = (element * length) / (max + 1);
element为当前元素的值,length为桶的大小,max为数组中最大元素的值
③ 因为输入的数据是随机的,所以有可能在一个桶中分布着好几个数据,那么怎么样维持在一个桶中的顺序呢?
因为涉及到桶中元素的数量的不确定性,所以我们可以使用动态的数据结构来存储,考虑到插入的操作是比较频繁的,所以这里我们使用链表来进行插入元素,并且在一个桶中维持从小到大的顺序
在一开始的时候我们扫描桶的元素,找到第一个比当前需要插入的元素大或者相等的的元素,那么将这个元素往前插入就可以了
解决了上面的问题之后那么我们就可以写代码了
3. 具体的代码如下:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int[n];
for(int i = 0; i < n; i++){
arr[i] = sc.nextInt();
}
sortByBucket(arr);
sc.close();
}
private static void sortByBucket(int[] arr){
int length = arr.length;
LinkedNode bucket[] = new LinkedNode[length];
//System.out.println(bucket.length);
int max = Util.maxOf(arr);
for(int i = 0; i < length; i++){
int index = hash(arr[i], length, max);
if(bucket[index] == null){
bucket[index] = new LinkedNode(arr[i]);
}else{
insertInto(arr[i], bucket[index], index, bucket);
}
}
int k = 0;
for (LinkedNode node : bucket) {
if (node != null) {
while (node != null) {
arr[k++] = node.value;
node = node.next;
}
}
}
for(int i = 0; i < length; i++){
System.out.print(arr[i] + " ");
}
}
private static void insertInto(int element, LinkedNode head, int index, LinkedNode[] bucket){
LinkedNode newNode = new LinkedNode(element);
if(element <= head.value){
newNode.next = head;
bucket[index] = newNode;
return;
}
LinkedNode p = head;
LinkedNode pre = p;
while(p != null && element > p.value){
pre = p;
p = p.next;
}
if(p == null){
pre.next = newNode;
}else{
pre.next = newNode;
newNode.next = p;
}
}
private static int hash(int element, int length, int max) {
return (element * length) / (max + 1);
}
}
4. 时间复杂度的问题
时间复杂度: O(N+C),其中C=N*(logN-logM),M为桶的个数