Вопросы по реализации сортировки Radix в Java

1

Следующая сортировка 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;
}

Какова цель этого сегмента кода? Благодарю!

Теги:
algorithm
sorting
bit-manipulation
radix-sort

1 ответ

4
Лучший ответ

Блок кода делает именно то, что говорит комментарий:

для наиболее значимого байта 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.

  • 0
    Спасибо, отличное объяснение! В этом случае этот сегмент кода действительно работает для int a[] который включает неотрицательные целые числа (в отличие от предположения автора кода в комментариях строки 4-5)?
  • 1
    да, если все целые числа находятся в типе int .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню