web-dev-qa-db-ja.com

基数ソートはどのように機能しますか?

なぜこれが私にとって頭を包むのがとても難しいのか分かりません。 Wikiページ、および(バケットに関して)基数ソートアルゴリズムがどのように機能するかを理解しようとする擬似コード(および実際のコード)を調べました。

ここで間違ったことを調べていますか?バケットの並べ替えを検討する必要がありますか?誰かが私にそれがどのように機能するかについての馬鹿げたバージョンを教えてもらえますか?参考のために、推定が基数ソートを実行するコードブロックを次に示します。

// 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];
37
MrDuk

数学では、基数は10進数が10を基数とする基数を意味します。

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

簡単にするために、ソートに10進数(= 10)を使用するとします。次に、番号を単位で分けてから、それらを再び組み合わせます。次に、数を10で区切り、それらを再び組み合わせます。その後、すべての数字が並べ替えられるまで、数百ずつ続けます。ループするたびに、リストを左から右に読むだけです。数字をバケットに分割していることも想像できます。これは5, 213, 55, 21, 2334, 31, 20, 430を使用した図です

単位で区切る:

  • ゼロ:20、430

  • 1:21、31

  • 2つ:

  • スリー:213

  • fours:2334

  • ファイブ:5、55

    一緒に戻る:20、430、21、31、213、2334、5、55

それらを元に戻すには、最初にzeroesバケットを読み、次にonesバケットを読み、それからninesバケットを読むまで続けます。

10で区切る:

  • ゼロ:05

  • もの:213

  • 2:20、21

  • threes:430、31、2334、

  • 四つんばい:

  • ファイブ:55

    一緒に戻る:5、213、20、21、430、31、2334、55

数百で区切る:

  • ゼロ:005、020、021、031、055

  • もの:

  • 2:213

  • スリー:2334

  • fours:430

  • ファイブ:

    一緒に戻る:5、20、21、31、55、213、2334、430

数千で区切る:

  • ゼロ:0005、0020、0021、0031、0031、0055、0213、0430

  • もの:

  • 2:2334

  • スリー:

  • 四つんばい:

  • ファイブ:

    一緒に戻る:5、20、21、31、55、213、430、2334

これで完了です。 Javapython の両方で、Geekviewpointでこのための素敵なコードを見ました

100
Konsol Labapen

カードのデッキを考えてください。最初にスーツで4つの山に並べ替えます。次に、これら4つの山を重ねて、ランクに基づいて13個の山に分類します。それらをまとめると、ソートされたデッキができました。

これがクイックソートの基本的な流れです。

1回目のパスの場合:カウントソートを使用して、最下位桁(1の位)に基づいて配列をソートします。元のリストでは435が835未満で発生したため、435が835未満であることに注意してください。

2回目のパス:では、カウントソートを使用して、次の桁(10桁)に基づいて配列をソートします。前のリストでは608が704未満で発生したため、ここでは608が704未満であることに注意してください。(835、435)および(751、453)も同様です。

3番目のパスの場合:カウントソートを使用して、最上位桁(100桁)に基づいて配列をソートします。前のリストでは435が453未満で発生したため、ここでは435が453未満であることに注意してください。(608、690)および(704、751)も同様です。

詳細については、 codingeekでこのブログを参照し、明確に理解することができます

1
Hitesh Garg