alw*_*lwc 3 java sorting algorithm bit-manipulation radix-sort
以下基数排序执行四次计数排序(256 个桶,32 位整数,从最低有效数字开始),取自Sedgewick 的算法教科书。
public class LSD {
private final static int BITS_PER_BYTE = 8;
// LSD sort an array of integers, treating each int as 4 bytes
// assumes integers are nonnegative
// [ 2-3x faster than Arrays.sort() ]
public static void sort(int[] a) {
int BITS = 32; // each int is 32 bits
int W = BITS / BITS_PER_BYTE; // each int is 4 bytes
int R = 1 << BITS_PER_BYTE; // each bytes is between 0 and 255
int MASK = R - 1; // 0xFF
int N = a.length;
int[] aux = new int[N];
for (int d = 0; d < W; d++) {
// compute frequency counts
int[] count = new int[R+1];
for (int i = 0; i < N; i++) {
int c = (a[i] >> BITS_PER_BYTE*d) & MASK;
count[c + 1]++;
}
// compute cumulates
for (int r = 0; r < R; r++)
count[r+1] += count[r];
// for most significant byte, 0x80-0xFF comes before 0x00-0x7F
if (d == W-1) {
int shift1 = count[R] - count[R/2];
int shift2 = count[R/2];
for (int r = 0; r < R/2; r++)
count[r] += shift1;
for (int r = R/2; r < R; r++)
count[r] -= shift2;
}
// move data
for (int i = 0; i < N; i++) {
int c = (a[i] >> BITS_PER_BYTE*d) & MASK;
aux[count[c]++] = a[i];
}
// copy back
for (int i = 0; i < N; i++)
a[i] = aux[i];
}
}
Run Code Online (Sandbox Code Playgroud)
除了这部分,我理解大部分代码:
if (d == W-1) {
int shift1 = count[R] - count[R/2];
int shift2 = count[R/2];
for (int r = 0; r < R/2; r++)
count[r] += shift1;
for (int r = R/2; r < R; r++)
count[r] -= shift2;
}
Run Code Online (Sandbox Code Playgroud)
这一段代码的目的是什么?谢谢!
代码块完全按照注释说的做:
对于最高有效字节,0x80-0xFF 在 0x00-0x7F 之前
原因是:由于您使用的是int,因此最重要的位是符号位。因此范围内最高有效字节的0x80-0xFF数字是负数,所以应该放在正数之前,正数在范围内具有最高有效字节0x00-0x7F。
如果你问代码块是如何实现的,这里有一个简单的想法:
由于您了解数据是如何移动的,所以我假设您了解count[]整个代码中的作用。在代码块,R是上界,这是0xFF + 1和R / 2是0x7F + 1。因此count[R] - count[R / 2]是在的范围内的总数目0x80来0xFF。因此,通过添加的转变count[R] - count[R / 2],以count[0 .. R / 2]从减去count[R / 2 .. R]的范围将帮助数0x00以0x7F具有更高的count价值不是数字的范围0x80来0xFF,这导致0x80-0xFF为0x00-0x7F之前说到最后。
最后,你可能会好奇:如果第一位是符号位,为什么11111111大于10000001?那不是-(127) < -(1)吗?这是因为在计算机系统中,我们使用的是2 的补码而不是有符号整数,因此11111111实际上意味着-1,10000001实际上意味着-127。