关于Java中基数排序实现的问题
Posted
技术标签:
【中文标题】关于Java中基数排序实现的问题【英文标题】:Questions on an implementation of Radix sort in Java 【发布时间】:2014-09-01 01:28:30 【问题描述】:以下基数排序执行四次计数排序(256 个桶,32 位整数,从最低有效位开始),取自 Sedgewick's Algorithms textbook。
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];
除了这部分以外的大部分代码我都懂:
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;
这段代码的目的是什么?谢谢!
【问题讨论】:
【参考方案1】:代码块完全按照注释所说的:
对于最高有效字节,0x80-0xFF 在 0x00-0x7F 之前
原因是:因为你使用的是int
,所以最重要的位是sign位。因此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
范围内的数字比0x80
到0xFF
范围内的数字具有更高的count
值,这导致 0x80-0xFF 最终出现在 0x00-0x7F 之前。
最后,你可能会好奇:如果第一位是符号位,为什么11111111
比10000001
大?不是-(127) < -(1)
吗?这是因为在计算机系统中,我们使用的是2's compliment而不是有符号整数,因此11111111
实际上表示-1
,而10000001
实际上表示-127
。
【讨论】:
谢谢,很好的解释!在这种情况下,这段代码实际上适用于包含非负整数的int a[]
(与代码作者在第 4-5 行注释中的假设相反)?以上是关于关于Java中基数排序实现的问题的主要内容,如果未能解决你的问题,请参考以下文章