我坚持以递归方式实现Radix排序

时间:2016-12-25 15:39:17

标签: java arrays sorting recursion radix-sort

我需要实现一个程序,以递归方式对0到99999之间的数字进行排序(这基本上是Radix排序)。该过程本身有点简单:用户键入一个包含main方法中的数字的数组。然后,main方法调用sort-method,我在其中创建一个名为' space'的二维数组。有10行1列。然后,我将数组中的每个数字除以数字,在第一次运行中为10.000。因此,例如,23456/10000 = 2,3456 = 2(在java中),因此,程序将此数字放在空格[2] [0]中,因此在第二行中。然后,我们取整行并扩展它,这是在putInBucket方法中完成的。我们这样做是为了确保我们可以将另一个数字放入同一行。

我们对'数字' -array中的每个数字执行此操作。然后,我们想要使用这些行并按照相同的原则再次对它们进行排序,但现在我们来看看第二个数字。我们想要从左到右,而不是从右到左。所以,如果我们的第二行看起来像这样

[23456,24567],

我们想要比较3和4,这导致23456< 24567.

我们在sort方法结束时的递归调用的帮助下完成此操作。现在,这就是我迷失的地方。我根本不知道如何操纵数字变量,以便能够使用每个数字的第二个,第三个......数字。在第一轮中,如你所见,这可以简单地通过除以10.000来完成,但我没有找到从这里走得更远的方法。

请注意:是的,这是一个家庭作业问题,因此,我只允许在这里使用原语。我们还没有通过math.pow(...)之类的东西。提前谢谢!

public static int[] sort(int[] numbers, int digit) {

  if (numbers.length == 0)
    return numbers;

  int[][]space = new int[10][1];
  int i, j = 0;

  for (j = 0; j < numbers.length; j++) {
    i = numbers[j] / digit;
    space[i][0] = numbers[j];
    space[i] = putInBucket(space[i], numbers[j]);
  }

  for (i = 0; i < space[i].length; i++) {
    sort(space[i], digit); //not sure how to work with digit here
  }

  return ... //not sure what to return here

}

private static int[] putInBucket(int[] bucket, int number) {

  int[] bucket_new = new int[bucket.length+1];

  for (int i = 1; i < bucket_new.length; i++) {
    bucket_new[i] = bucket[i-1];
  }

  return bucket_new;

}

public static void main (String [] argv) {

  int[] numbers = IO.readInts("Numbers: ");
  int digit = 10000;
  int[] bucket = sort(numbers, digit); 

}

2 个答案:

答案 0 :(得分:2)

要提取最后一位数,余数运算符%是您的朋友:

123 % 10 == 3

如果您尚未涵盖%运算符,则可以使用

123 % 10 == 123 - (123 / 10 * 10) == 3

要提取另一个数字,您可以先使用/

将其移至最后
123 / 10 == 12
12 % 10 == 2

因此,您可以使用

提取任意数字
(number / mask) % 10 

其中掩码∈{...,10000,1000,100,10,1}。

额外信用

基数排序通常在二进制数系统中实现,因为可以提取二进制数字(或其序列)而不执行除法,这更有效:

x % 16 == x & 15;
x \ 16 == x >> 4;

此外,如果您要实现这一点,您需要一种更有效的方法来增加存储桶(您的实现需要O(n)将单个元素添加到存储桶,向存储桶添加n个元素因此需要O (n ^ 2),这使得你的基数排序比插入排序慢)。 Dynamic arrays通常使用效率更高的geometric expansion实现。

答案 1 :(得分:1)

这应该有效:

public static int[] sort(int[] numbers, int digit) {

     if (numbers.length == 0 || digit <= 0)
           return numbers;

     int[][]space = new int[10][10];
     int[] len = new int[10];
     int i, j = 0;

      for (j = 0; j < numbers.length; j++) {
            i = (numbers[j] / digit) % 10;
            len[i]++;
            for (int k = len[i] - 1; k > 0; k--) {
                space[i][k] = space[i][k - 1];
            }
            space[i][0] = numbers[j];
      }


      for (i = 0; i < 10; i++) {
          int[] bucket = new int[len[i]];
          for (int k = 0; k < len[i]; k++) 
              bucket[k] = space[i][k];
          space[i] = sort(bucket, digit / 10); 
      }

      int k = 0;

      for (i = 0; i < 10; i++) {
          for (j = 0; j < len[i]; j++) {
              numbers[k] = space[i][j];
              k++;
          }
      }

      return numbers; 

}

a)首先,space被分配为只有一列。因此,space[i] = bucket将不起作用。

相反,你可以将它声明为int [10] [10]。 (注意:一个桶中最多只能支持10个值)。或者您可以以编程方式分配新数组。或者当然,List可能更适合。

b)i = (numbers[j] / digit) % 10;

仅获取所需的数字。例如:如果数字为12130digit = 1000,我们要将i设置为2,而不是12

c)putInBucket替换为就地循环。

d)对于bucket的每个space,我们通过递归调用sort将其排序一位数。

e)最后,返回的结果(numbers)可以通过将space从数字0循环到9来创建。

注意: 这个解决方案可能会变得更好。