内容介绍
基数排序简介
前面学过计数排序和桶排序都是非基于比较的排序算法,它们的优势在于对一定范围内的数据排序时可以突破基于比较排序算法的时间复杂度O(nlogn)。
基数排序是一种非比较型整数排序算法,基数排序的发明可以追溯到1887年赫尔曼·何乐礼在打孔卡片制表机(Tabulation Machine)上的贡献。
基数排序的思想
基数排序(Radix Sort)是计数排序的扩展,它的基本思想是:将整数按位数分割成不同的数字,然后按每个位数分别比较。
具体做法是:将所有待排序数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后从最低位开始,依次进行排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序数列。
基数排序动画演示
假设有{16, 28, 19, 65, 95, 98, 81, 77, 18, 15}这10个数据。一般没有特殊要求排序算法都是升序排序,小的在前,大的在后,效果如下:
基数序分析
通过上面动画可以看出基数排序就是将数字按位分割,每一位进行一次计数排序,最终完成排序。
首先使用个位进行一次计数排序,效果如下:
接着使用十位进行计数排序,效果如下:
最终排序效果如下:
基数排序代码编写
public class RadixSort {
public static void main(String[] args) {
int[] arr = {16, 28, 19, 65, 95, 98, 81, 77, 18, 15};
radixSort(arr);
System.out.println("排序后: " + Arrays.toString(arr));
}
public static void radixSort(int[] arr) {
// 获取数组中最大元素
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max)
max = arr[i];
}
// 按位进行计数排序
for (int exp = 1; max/exp > 0; exp *= 10) {
countingSort(arr, exp);
System.out.println("radixSort = " + Arrays.toString(arr));
}
}
private static void countingSort(int[] arr, int exp) {
// 1.定义统计数组
int[] countArr = new int[10];
// 2.遍历源数组,获取每个数据,按位放到指定位置
for (int i = 0; i < arr.length; i++) {
countArr[arr[i]/exp%10]++;
}
// 3.对辅助数组进行加工处理
for (int i = 1; i < countArr.length; i++) {
countArr[i] += countArr[i-1];
}
// 5.倒序遍历源数组
// 已排序数组和待排序数组一样长
int[] sortedArr = new int[arr.length];
for (int i = arr.length-1; i >= 0; i--) {
// 从源数组中取出数据
int num = arr[i];
sortedArr[countArr[num/exp%10] - 1] = num;
// 辅助数组中该数据的数量减一,也就是后续相同数据放到前面一个位置
countArr[num/exp%10]--;
}
// 6.将已排序的数据放到待排序的数组中
for (int i = 0; i < sortedArr.length; i++) {
arr[i] = sortedArr[i];
}
}
}
基数排序的方式
基数排序的方式可以分为LSD和MSD两种:
LSD最低位优先(Least Significant Digit first)法,简称LSD法:先从最低(最右边)位开始排序,再对倒数第二低位进行排序,依次重复,直到对最高位排序后便得到一个有序序列。我们上面的案例就是先按个位排序,再按十位排序就属于最低位优先(LSD)。MSD最高位优先(Most Significant Digit first)法,简称MSD法:先从最高位(最左边)开始排序,再对第二高位进行排序,依次重复,直到对最低位排序后便得到一个有序序列。
基数排序的复杂度
空间复杂度:每位进行排序时,需要一个长度为10的辅助数组来统计出现的次数,还需要一个长度和待排序数组一样的数组来存放当前当前这次计数排序的结果,所以空间复杂度为O(n)
时间复杂度:1.获取数组中最大元素操作次数n,2.遍历源数组,获取每个数据,按位放到指定位置操作次数n,3.对辅助数组进行加工处理操作次数10,4.倒序遍历源数组进行排序操作次数n,5.将已排序的数据放到待排序的数组中操作次数n,总的操作次数为:4n+10,所以总的时间复杂度为O(n)。
总结
基数排序(Radix Sort)是计数排序的扩展,它的基本思想是:将整数按位数分割成不同的数字,然后按每个位数分别比较。
具体做法是:将所有待排序数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后从最低位开始,依次进行排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序数列。
基数排序的方式可以分为LSD和MSD两种。
---------- End ----------
原创文章和动画制作真心不易,您的点赞就是最大的支持!
想了解更多文章请关注微信公众号:表哥动画学编程