Если мне просто нужно отсортировать строки, состоящие из символов ASCII, мне интересно, в чем разница между использованием наиболее значимых v.s. наименее значимая сортировка по системе счисления? Я думаю, что у них должны быть такие же результаты, но их смущает следующее утверждение из ссылки ниже, и если кто-то может помочь прояснить, это будет здорово.

https://en.wikipedia.org/wiki/Radix_sort

Для сортировки ключей в лексикографическом порядке можно использовать сортировку по основанию счисления по старшим разрядам (MSD). В отличие от сортировки по основанию с наименьшей значащей цифрой (LSD), сортировка по основанию счисления по наиболее значимой цифре не обязательно сохраняет исходный порядок повторяющихся ключей.

Заранее спасибо, Лин

3
Lin Ma 22 Фев 2016 в 04:20

2 ответа

Лучший ответ

Сортировка LSD по основанию может логически объединять отсортированные ячейки после каждого прохода (считайте их одним ячейкой при использовании сортировки по счетчику / основанию). Сортировка по основанию MSD должна рекурсивно сортировать каждую ячейку независимо после каждого прохода. При сортировке по байтам это 256 ячеек после первого прохода, 65536 ячеек после второго прохода, 16777216 (16 миллионов) ячеек после третьего прохода, ...

Вот почему старые сортировщики карт сначала сортируют данные LSD. Ссылка на видео одного из них в действии. Карты загружаются и падают в лотки лицевой стороной вниз. В видео сортировщик карт сбрасывает карты в ячейки от "0" до "9", затем оператор берет карты из ячейки 0, затем берет карты из ячейки 1 и помещает их сверху (позади) ячейки 0. карты, затем 2 корзины идут за колоду и так далее, «объединяя» карты из корзин. Для больших колод карт над сортировщиком карт должны быть установлены полки над каждой корзиной для размещения карт, когда колоды слишком велики, чтобы их можно было держать рукой.

http://www.youtube.com/watch?v=jJH2alRcx4M

Пример поразрядной сортировки C ++ LSD для 32-битных целых чисел без знака, где каждая «цифра» является байтом. Большая часть кода генерирует матрицу счетчиков, которые преобразуются в индексы, отмечающие границы между ячейками переменного размера. Фактическая сортировка по основанию системы счисления находится в последнем вложенном цикле.

//  a is input array, b is working array
uint32_t * RadixSort(uint32_t * a, uint32_t *b, size_t count)
{
size_t mIndex[4][256] = {0};            // count / index matrix
size_t i,j,m,n;
uint32_t u;
    for(i = 0; i < count; i++){         // generate histograms
        u = a[i];
        for(j = 0; j < 4; j++){
            mIndex[j][(size_t)(u & 0xff)]++;
            u >>= 8;
        }       
    }
    for(j = 0; j < 4; j++){             // convert to indices
        m = 0;
        for(i = 0; i < 256; i++){
            n = mIndex[j][i];
            mIndex[j][i] = m;
            m += n;
        }       
    }
    for(j = 0; j < 4; j++){             // radix sort
        for(i = 0; i < count; i++){     //  sort by current lsb
            u = a[i];
            m = (size_t)(u>>(j<<3))&0xff;
            b[mIndex[j][m]++] = u;
        }
        std::swap(a, b);                //  swap ptrs
    }
    return(a);
}
6
rcgldr 23 Фев 2016 в 09:27

Часть, которая вас сбивает с толку, заключается в том, что почти ВСЕ LSD-сортировки по основанию сохраняют порядок повторяющихся ключей. Это потому, что они вообще полагаются на это свойство. Например, если у вас есть 2 таких итерации, сортировка сначала по разрядам единиц, а затем по разрядам десятков:

22        21        11
21   ->   11   ->   21
11        22        22

Когда мы сортируем по десяткам, нам нужно сохранить порядок разрыва связей, который мы получили при сортировке по единицам, чтобы 21 и 22 выходили в правильном порядке, даже если они имеют одинаковые цифры в разряде десятков. Если вы реализуете первую сортировку (по одному) так же, как должны делать все остальные (а почему бы и нет?), То сортировка будет стабильной.

Радиксная сортировка MSD может быть записана с использованием тех же шагов сортировки, что и LSD-сортировка, и в этом случае она также будет стабильной. Но есть и другие, часто более эффективные способы реализовать сортировку по основанию MSD, у которых нет этого свойства.

Сортировки по основанию MSD, которые не сохраняют порядок или дубликаты обычно находятся на месте, т.е. они работают без выделения отдельного массива для хранения отсортированных элементов.

ОБРАТИТЕ ВНИМАНИЕ, что ничего из этого не имеет значения, если вы просто сортируете список строк, сравнивая их кодовые точки ASCII. «сохранение порядка повторяющихся ключей» имеет значение только тогда, когда к ним прикреплена дополнительная информация. Например, если ключи имеют связанные значения или если вы выполняете сортировку без учета регистра и хотите, чтобы «Abe» и «abE» выводились в том же порядке, в котором они пришли.

2
Matt Timmermans 22 Фев 2016 в 12:41