1、简单介绍
1、对电话号码进行排序我们这里也可以借助相同的处理思路,先按照最后一位来排序手机号码,然后,再按照倒数第二位重新排序,以此类推,最后按照第一位重新排序。经过 11 次排序之后,手机号码就都有序了。
2、基数排序:根据每一位来排序,我们可以用刚讲过的桶排序或者计数排序,它们的时间复杂度可以做到O(n)。如果要排序的数据有 k 位,那我们就需要 k 次桶排序或者计数排序,总的时间复杂度是O(k*n)。当 k 不大的时候,比如手机号码排序的例子,k 最大就是 11,所以基数排序的时间复杂度就近似于 O(n)。
3、基数排序是一个稳定的排序。
4、基本思想:我们对一个相同长度,并且是每一位取值范围不大的数,进行计数或者桶排序。
5、基数排序对要排序的数据是有要求的,需要可以分割出独立的“位”来比较,而且位之间有递进的关系,如果 a 数据的高位比 b 数据大,那剩下的低位就不用比较了。除此之外,每一位的数据范围不能太大,要可以用线性排序算法来排序,否则,基数排序的时间复杂度就无法做到 O(n) 了。
2、代码实现
/**
* 基数排序
*/
public void radix_sort(int[] arr) {
//获取最大值
int max = getMax(arr);
int exp = max / 10;
//对各位 十位 千位 进行排序
for (int i = 1; i <= exp; i = i * 10) { //对每一位元素进行计数排序
count_sort(arr, exp);
}
}
private void count_sort(int[] arr, int exp) {
//1、因为全部是数字0-9 ,我们按照 10个来计数
int num = 10;
int b[] = new int[10];
//每一个元素出现的次数
for (int i = 0; i < arr.length; i++) {
b[arr[i] / exp % 10]++;
}
//统计小于等于它的元素个数
for (int j = 1; j < arr.length; j++) {
b[j] = b[j - 1] + 1;
}
int[] c = new int[arr.length];
//进行末尾开始比较是为了保证稳定性。
for (int i = arr.length - 1; i >= 0; i--) { // b[arr[i]/exp%10] 表示的是小于等于它的元素出现的次数
c[b[arr[i] / exp % 10] - 1] = arr[i];
b[arr[i] / exp % 10]--;
}
//进行赋值操作
for (int j = 0; j < arr.length; j++) {
arr[j] = c[j];
}
}
3、应用
1、我们可以用基数排序来实现电话号码的排序,时间复杂度只需要O(n);
2、可以对英文单词进行排序。