1.基数排序介绍
(1)基数排序属于”分配式排序“,又称”桶子法“,顾名思义,它是通过键值的各个位的值,将要排序的元素分配至某些”桶“中,达到排序的作用。
(2)基数排序属于稳定排性的排序,基数排序法是效率高的稳定性排序法。
(3)基数排序是桶排序的扩展,速度很快。
(4)基数排序是金典的以空间换时间的方式,占用内存很大,对海量数据排序时,容易造成OOM。
(5)有负数的数组,不适合用基数排序。
(6)基数排序是1887年赫尔曼.何乐礼发明的。它是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较。
(7)基数排序将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
2.示意图
3.代码实现
@Test
public void testSort(){
//我们来测一下各种排序速度
int[] array = new int[100000];
for (int i = 0; i < array.length; i++) {
array[i] = (int) (Math.random()*100000);
}
long start = System.currentTimeMillis();
//bubbleSorting(array);//冒泡排序排序100000个数总耗时17984毫秒
//selectSorting(array);//选择排序排序100000个数总耗时3203毫秒
//insertSorting(array);//直接插入排序100000个数总耗时1109毫秒
//shellSortByExchange(array);//希尔的交换排序100000个数总耗时7829毫秒
//shellSortByMove(array);//希尔的移动排序100000个数总耗时16毫秒
//quickSort(array,0,array.length-1);//快速排序的移动排序100000个数总耗时31毫秒
//mergeSort(array,0,array.length-1,new int[array.length]);//归并排序的移动排序100000个数总耗时16毫秒
cardinalitySort(array);//基数排序的移动排序100000个数总耗时31毫秒
long end = System.currentTimeMillis();
System.out.println("总共耗时:"+(end-start));
}
public void cardinalitySort(int[] array) {
//得到数组中最大数的位数,从而得到循环的次数
int max = array[0];
for (int i = 1; i < array.length; i++) {
if (max < array[i]) {
max = array[i];
}
}
int digit = (max+"").length();
/*
* 定义一个二位数组,二位数组包含10个一维数组
* 对应着0-9这10个桶,而每个桶的最大容量就是array.length
*/
int[][] bucket = new int[10][array.length];
//还需一个一维数组来记录每个桶中实际放入数据的个数
int[] buckerElementCounter = new int[10];
//n=1表示先取个位
for (int i = 0, n = 1; i < digit; i++, n*=10) {
for (int j = 0; j < array.length; j++) {
//取出每个元素相应位数上对应的值
int element = array[j]/n%10;
//放入对应的桶中
bucket[element][buckerElementCounter[element]] = array[j];
//桶中的元素加一
buckerElementCounter[element]++;
}
int index = 0;
//按照桶中元素的顺序,把这些元素放入原数组中
for (int k = 0; k < buckerElementCounter.length; k++) {
//先要判断桶中有没有数据
if (buckerElementCounter[k] != 0) {
for (int j = 0; j < buckerElementCounter[k]; j++) {
array[index++] = bucket[k][j];
}
}
//处理完每个桶后,要把桶中的元素个数置为0
buckerElementCounter[k] = 0;
}
}
}