Как работает Radix Sort?

Я не знаю, почему мне так трудно уложить это в голове. Я просмотрел вики-страницы и псевдокод (а также фактический код), пытаясь понять, как работают алгоритмы сортировки по основанию (относительно корзин).

Я смотрю на неправильную вещь здесь? Может быть, мне стоит заняться сортировкой ведра? Может ли кто-нибудь дать мне упрощенную версию того, как это работает? Для справки, вот кодовый блок, который предположительно выполняет сортировку по основанию:

// Sort 'size' number of integers starting at 'input' according to the 'digit'th digit
// For the parameter 'digit', 0 denotes the least significant digit and increases as significance does
void radixSort(int* input, int size, int digit)
{
    if (size == 0)
        return;

    int[10] buckets;    // assuming decimal numbers

    // Sort the array in place while keeping track of bucket starting indices.
    // If bucket[i] is meant to be empty (no numbers with i at the specified digit),
    // then let bucket[i+1] = bucket[i]

    for (int i = 0; i < 10; ++i)
    {
        radixSort(input + buckets[i], buckets[i+1] - buckets[i], digit+1);
    }
}

И я также рассмотрел нерекурсивные решения:

void radixsort(int *a, int arraySize)
{
    int i, bucket[sortsize], maxVal = 0, digitPosition =1 ;
    for(i = 0; i < arraySize; i++) {
        if(a[i] > maxVal) maxVal = a[i];
    }

    int pass = 1; 
    while(maxVal/digitPosition > 0) {
        // reset counter 
        int digitCount[10] = {0};

        // count pos-th digits (keys) 
        for(i = 0; i < arraySize; i++)
            digitCount[a[i]/digitPosition%10]++;

        // accumulated count 
        for(i = 1; i < 10; i++)
            digitCount[i] += digitCount[i-1];

        // To keep the order, start from back side
        for(i = arraySize - 1; i >= 0; i--)
            bucket[--digitCount[a[i]/digitPosition%10]] = a[i];

        for(i = 0; i < arraySize; i++)
            a[i] = bucket[i];

        cout << "pass #" << pass++ << ": ";
        digitPosition *= 10;
    } 

}

В частности, эта линия доставляет мне проблемы. Я пытался пройтись по нему с ручкой и бумагой, но я до сих пор не могу понять, что это делает:

   // To keep the order, start from back side
        for(i = arraySize - 1; i >= 0; i--)
            bucket[--digitCount[a[i]/digitPosition%10]] = a[i];

person MrDuk    schedule 05.02.2013    source источник
comment
en.wikipedia.org/wiki/Radix_sort#Examples содержит отличный пример.   -  person user218867    schedule 12.03.2020


Ответы (4)


В математике основание счисления означает основание, где десятичное число будет основанием 10. Представьте, что у вас есть числа, некоторые из которых имеют более одной цифры, например

5, 213, 55, 21, 2334, 31, 20, 430

Для простоты предположим, что вы хотите использовать десятичную систему счисления (=10) для сортировки. Затем вы должны начать с разделения чисел на единицы, а затем снова сложить их вместе; затем вы должны были разделить числа на десятки, а затем снова сложить их вместе; затем по сотням и так далее, пока все числа не будут отсортированы. Каждый раз, когда вы зацикливаетесь, просто читайте список слева направо. Вы также можете представить, что вы разделяете числа на ведра. Вот иллюстрация с использованием 5, 213, 55, 21, 2334, 31, 20, 430

Разделить по единицам:

  • нули: 20, 430

  • единицы: 21, 31

  • двойки:

  • тройки: 213

  • четверки: 2334

  • пятерки: 5, 55

    Снова вместе: 20, 430, 21, 31, 213, 2334, 5, 55

Чтобы собрать их вместе, сначала прочитайте ведро zeroes, затем ведро ones и так далее, пока не прочитаете ведро nines.

Разделите по десяткам:

  • нули: 05

  • штук: 213

  • двойки: 20, 21

  • тройки: 430, 31, 2334,

  • четверки:

  • пятерки: 55

    Снова вместе: 5, 213, 20, 21, 430, 31, 2334, 55

Разделяйте по сотням:

  • нули: 005, 020, 021, 031, 055

  • те:

  • двойки: 213

  • тройки: 2334

  • четверки: 430

  • пятерки:

    Снова вместе: 5, 20, 21, 31, 55, 213, 2334, 430

Разделить на тысячи:

  • нули: 0005, 0020, 0021, 0031, 0055, 0213, 0430

  • те:

  • двойки: 2334

  • тройки:

  • четверки:

  • пятерки:

    Снова вместе: 5, 20, 21, 31, 55, 213, 430, 2334

Теперь вы сделали. Я видел хороший код для этого на Geekviewpoint как в Java, так и в python

person Konsol Labapen    schedule 06.02.2013
comment
Ух ты! Это много деталей. Вы действительно пошли на это там. Прекрасная работа. +1 - person kasavbere; 06.02.2013
comment
@kasavbere Я очень признателен stackoverflow и очень уважаю людей, которые просят о помощи. - person Konsol Labapen; 06.02.2013
comment
Не могли бы вы также объяснить, как это изменит сортировку по основанию, если нам нужно будет использовать другую базу? Например наше максимальное число будет 1 000 000 ^ 2, поэтому, если я правильно угадал, мы могли бы использовать основание 256. Но как это изменит алгоритм? - person frank17; 04.10.2016
comment
я просто обожаю, когда кто-то объясняет абсолютно непрофессионально, разбивая вещи на клеточном уровне!! :D - person NoobEditor; 17.01.2017

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

person 500 - Internal Server Error    schedule 05.02.2013
comment
sort .. на основе ранга является плохой аналогией для сортировки по основанию, поскольку подразумевает сравнение при упорядочении. например: когда я сортирую набор карт вручную, я кладу 4 перед 9, затем 5 после 4, но перед 9 и 3 перед 4 и т. д.. - person ; 06.02.2013
comment
@pst: Пожалуйста, уточните - как это подразумевает заказ? - person 500 - Internal Server Error; 06.02.2013
comment
Это подразумевает сравнение при заказе. Аналогии моделируют реальную жизнь — и в этом случае, согласно описанной мной операции, аналогия расходится с тем, что она пытается описать. Первая часть, о четырех стопках это то, что касается сортировки по основанию, только с одним ограничением: стопки всегда ранжируются в определенном порядке. (И такой порядок потому, что кто-то так сказал, а не из-за какого-то сравнения колод.) - person ; 06.02.2013
comment
Я предполагаю, что это можно прочитать в обоих направлениях (и я не совсем уверен в своем чтении): +1, но было бы неплохо, чтобы этот ответ был более размытым. - person ; 06.02.2013
comment
я не знаю. я думаю, это работало бы лучше, если бы это было что-то вроде... у вас есть 13 слотов/сегментов для ранга, вы кладете карты в соответствующий слот, а затем возвращаете их из самого нижнего слота в самый высокий слот. альт. они отсортированы. вам не нужно было делать никаких сравнений. - person thang; 06.02.2013

Это основной поток быстрой сортировки.

Для первого прохода: мы сортируем массив по наименьшей значащей цифре (1-е место) с помощью сортировки подсчетом. Обратите внимание, что 435 ниже 835, потому что 435 оказалось ниже 835 в исходном списке.

Для 2-го прохода: мы сортируем массив на основе следующей цифры (10-й разряд), используя сортировку подсчетом. Обратите внимание, что здесь 608 ниже 704, потому что 608 оказалось ниже 704 в предыдущем списке, и аналогично для (835, 435) и (751, 453).

Для третьего прохода: мы сортируем массив по старшей значащей цифре (сотые разряды) с помощью сортировки подсчетом. Обратите внимание, что здесь 435 ниже 453, потому что 435 оказалось ниже 453 в предыдущем списке, и аналогично для (608, 690) и (704, 751).

Для получения дополнительной информации вы можете обратиться к этому блогу на codingeek и получить четкое понимание.

person Hitesh Garg    schedule 13.02.2017

может быть, мой код может помочь вам :)

Вот код python для Radix Sort:

import random,time

from random import randint

A=[random.randint(1,1212) for i in range(23)]


length = len(str(max(A)))

print(length) 

rang = 10

print(A)

start=time.time()

for i in range(length):

B = [[] for k in range(rang)]

for x in A:

    figure =x // (10**i) % 10

    B[figure].append(x)

A = []

for k in range(rang):

    A+=B[k]

end=time.time()

print(end-start)

print(A)
person Hayk Eminyan    schedule 30.04.2020