Следующая сортировка Radix выполняет четыре прохода сортировки (256 кодов, 32-битные целые числа, начиная с младших значащих цифр), взятых из учебника по алгоритму Sedgewick Algorithms.
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;
}
Какова цель этого сегмента кода? Благодарю!
Блок кода делает именно то, что говорит комментарий:
для наиболее значимого байта 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
.
int a[]
который включает неотрицательные целые числа (в отличие от предположения автора кода в комментариях строки 4-5)?int
.