基数排序及java代码实现

前言:原文作者Leo-Yang。我不生产代码,我只是代码的搬运工

基数排序(radix sort)又称桶排序(bucket sort),相对于常见的比较排序,基数排序是一种分配式排序,即通过将所有数字分配到应在的位置最后再覆盖到原数组完成排序的过程。

首先既然作为分配式排序,联想计数排序,每一位排序时存储该次排序结果的数据结构应该至少是一个长度为10的数组(对应十进制该位0-9的数字)。同时可能存在以下情况:原数组中所有元素在该位上的数字都相同,那一维数组就没法满足我们的需要了,我们需要一个10*n(n为数组长度)的二维数组来存储每次位排序结果。熟悉计数排序结果的读者可能会好奇:为什么不能像计数排序一样,在每个位置只存储出现该数字的次数,而不存储具体的值,这样不就可以用一维数组了?这个我们不妨先思考一下,在对基数排序分析完之后再来看这个问题。

算法过程

初始化:构造一个10*n的二维数组,一个长度为n的数组用于存储每次位排序时每个桶子里有多少个元素。 2.循环操作:从低位开始(我们采用LSD的方式),将所有元素对应该位的数字存到相应的桶子里去(对应二维数组的那一列)。然后将所有桶子里的元素按照桶子标号从小到大取出,对于同一个桶子里的元素,先放进去的先取出,后放进去的后取出(保证排序稳定性)。这样原数组就按该位排序完毕了,继续下一位操作,直到最高位排序完成。 下面给出一个实例帮助理解: 我们现有一个数组:73, 22, 93, 43, 55, 14, 28, 65, 39, 81 下面是排序过程(二维数组里每一列对应一个桶,因为桶空间没用完,因此没有将二维数组画全):

1.按个位排序


按第一位排序后数组结果: 81,22,73,93,43,14,55,65,28,39

可以看到数组已经按个位排序了。

 2根据个位排序结果按百位排序


取出排序结果: 14,22,28,39,43,55,65,73,81,93

可以看到在个位排序的基础上,百位也排序完成(对于百位相同的数子,如22,28,因为个位已经排序,而取出时也保持了排序的稳定性,所以这两个数的位置前后是根据他们个位排序结果决定的)。因为原数组元素最高只有百位,原数组也完成了排序过程。

我们现在来看看之前遗留的两个问题:为什么不能用一维数组,一定要用二维数组这样的类似桶的结构来存储中间位排序结果?其实之所以要写这个问题,是因为我觉得这个问题是理解基数排序的关键。基数排序本身原理很简单,但是实现中有两个问题需要考虑:1.怎么保留前一位的排序结果,这个问题用之前提到的排序稳定性可以解决。2.怎么关联该位排序结果和原数组元素,二维数组正是为了解决这个问题使用的办法。在计数排序里,虽然保留了所有相等的元素的相对位置,但是这些相等的元素在计数排序里实际是没有差别的,因此我们可以只保存数组里有多少个这样的元素即可。而基数排序里不同,有些元素虽然在某一位上相同,但是他们其他位上很可能不同,如果只保存该位上有多少个5或者多少个6,那关于元素其他位的信息就都丢弃了,这样也就没法对这些元素更高位进行排序了。 弄清基数排序的过程后,我们来看看这个算法的时间复杂度是多少?每次循环遍历数组将元素放在指定位置Θ(n),在从桶中取出数据Θ(n),循环d次(d是位数),时间复杂度就是Θ(r*n)

基数排序的java实现:

你可能感兴趣的:(基数排序及java代码实现)