右(LSB)基数 - 如何处理2的补码?

时间:2014-04-19 11:08:21

标签: java algorithm sorting radix-sort

我正在尝试为整数实现右/ LSB基数排序,一旦它正常工作,我将尝试并行化它。我的顺序代码适用于无符号数,但是一旦我将负整数投入其中,它就不会看到""有符号位,最后是从0到 n 的正(排序)整数,以及从 -n 到-1的负(再次排序)整数。

这是我的代码:

public class SeqRadix {
    static void radix2(int[] a) {

        // 2 digit radixSort: a[]
        int max = a[0];
        int numBit = 2;
        int n = a.length;

        // a) find max value in a[]
        for (int i = 1; i < n; i++){
            if (a[i] > max) {
                max = a[i];
            }
        }
        while (max >= (1 << numBit)){
            numBit++; // digits in max
        }
        // decide num of bits in bit1 and bit2
        int bit1 = numBit / 2, bit2 = numBit - bit1;
        int[] b = new int[n];
        radixSort(a, b, bit1, 0); // first digit from a[] to b[]
        radixSort(b, a, bit2, bit1);// second digit, back from b[] to a[]
    } // end

    /**
     * Sort a[] on one digit ; number of bits = maskLen, shiftet up �shift�
     * bits
     */
    static void radixSort(int[] a, int[] b, int maskLen, int shift) {
        int acumVal = 0, j, n = a.length;
        int mask = (1 << maskLen) - 1;
        int[] count = new int[mask + 1];

        // b) count=the frequency of each radix value in a
        for (int i = 0; i < n; i++) {
            count[(a[i] >> shift) & mask]++;
        }

        // c) Add up in 'count' - accumulated values
        for (int i = 0; i <= mask; i++) {
            j = count[i];
            count[i] = acumVal;
            acumVal += j;
        }
        // c) move numbers in sorted order a to b
        for (int i = 0; i < n; i++) {
            b[count[(a[i] >> shift) & mask]++] = a[i];
        }
    }// end radixSort
}// end SekvensiellRadix

首先对LSB进行排序,然后越来越多的重要位,即2位补码/有符号位似乎没有被捕获。提前谢谢!

2 个答案:

答案 0 :(得分:2)

您需要做的是反转符号位上的比较操作。对于每个其他位0 < 1,但对于符号位,我们使用1 < 0。在对0到30位进行排序时(显然对于32位整数),可以对该整数的幅度进行排序。不是绝对的,因为有一个班次,但相对于同一个符号的所有其他整数,这就是我们所需要的。

所以,如果我们有数字{5,-1,3,2,-3,-8}(为简单起见,带符号的4位):

0101 =  5
1111 = -1
0011 =  3
0010 =  2
1101 = -3
1000 = -8

排序到第2位后,我们有:

1 000 = -8
0 010 =  2
0 011 =  3
0 101 =  5
1 101 = -3
1 111 = -1

请注意,每个负数都按相对于其他负数的递增顺序排序。 (同样是积极的。)现在,为了比较符号位,我们说1 < 0。这会将所有负数移到列表的前面,因为我们使用稳定的排序机制,所有负数都保持相对于彼此的相同位置。 (同样,对于积极因素。)

最后,我们的列表按升序排序:

1000  = -8
1101  = -3
1111  = -1
0010  =  2
0011  =  3
0101  =  5

答案 1 :(得分:1)

您只需要在对它们做出决策时通过反转第31位将所有int值转换为无符号值:

unsigned = signed ^ 0x80000000;

或者,如果您发现实施起来更方便,请反转基于第31位做出的所有决策的结果。

编辑:当您尝试查找最大值时已经开始 - 搜索最大值的方式您将永远找不到第31位设置为最大值的值。你需要使用无符号比较(java不支持语言方式),所以在比较之前翻译第31位:

    // a) find max value in a[]
    for (int i = 1; i < n; i++){
        if ((a[i]^0x80000000) > (max^0x80000000)) {
            max = a[i];
        }
    }