一、基数排序思想
相比其它排序,主要是利用比较和交换,而基数排序则是利用分配和收集两种基本操作。基数 排序是一种按记录关键字的各位值逐步进行排序的方法。此种排序一般适用于记录的关键字为整数类型的情况。所有对于字符串和文字排序不适合。(O(d(n+k))* : n个d位数,取值范围[0,k],对于每一位,耗时O(n+k), 稳定排序)
实现:将所有待比较数值(自然数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
基数排序的两种方式:
- 高位优先,又称为最有效键(MSD),它的比较方向是由右至左; 从低位到高位
- 低位优先,又称为最无效键(LSD),它的比较方向是由左至右;(可能会出现错误)
二、图解
其实,说实在的,就是先低位排,然后排高位,从而到最后是有序的,因为后一次排的要依赖前一次排的。举个例子,22,23,因为之前按个位数拍过序了,所以23在22后面,现在依次遍历,22肯定先于23判断,所以排在23前面。(代码是从后往前整的,但是道理是一个道理。)
三、代码:
public class Test1 {
public static void main(String[] args) {
int []arr= {80,14,8,92,26,73,41,67,33};
radixSort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 高位优先法(MSD)从低到高
*
* @param arr 待排序列,必须为自然数
*/
private static void radixSort(int[] arr)
{
// 代排序列最大值
int max=arr[0];
// 指数
int exp;
// 计算最大值
for(int val : arr) {
max=Math.max(max,val);
}
for(exp=1;max/exp>0;exp*=10) {
// 存储待排元素的临时数组
int []temp=new int [arr.length];
// 分桶个数
int[] buckets=new int[10];
// 将数据出现的次数存储在buckets中
for(int val :arr) {
// (val/exp)%10:value的最低位(个数)
int zuiDiWei=(val/exp)%10;
buckets[zuiDiWei]++;
}
//更改buckets[i],前缀和,确定每个数的位置
for(int i=1;i<10;i++) {
//System.out.print(buckets[i]+" ");
buckets[i]+=buckets[i-1];
}
// 将数据存储到临时数组temp中
// 大的在后面 所以倒序,很巧妙
for(int i=arr.length-1;i>=0;i--){
int zuiDiWei=(arr[i]/exp)%10;
temp[buckets[zuiDiWei]-1]=arr[i];
buckets[zuiDiWei]--;
}
//将有序元素temp赋给arr
System.arraycopy(temp,0,arr,0,arr.length);
//System.out.println(Arrays.toString(arr));
}
}
}