インプレース基数ソート
これは長いテキストです。我慢してください。要約すると、問題は、実行可能なインプレース基数ソートアルゴリズムがあるかどうかです。 予備的 「A」、「C」、「G」、および「T」の文字のみを使用する小さな固定長の文字列が大量にあります(そうです、ご想像のとおり、DNAです)。 現時点では、STLのすべての一般的な実装でintrosortを使用std::sortします。これはかなりうまくいきます。しかし、基数ソートは私の問題セットに完全に適合し、実際にははるかにうまく機能するはずだと確信しています。 細部 私はこの仮定を非常に単純な実装でテストしました。比較的小さな入力(10,000程度)の場合、これは真実でした(少なくとも、2倍以上の速さ)。ただし、問題のサイズが大きくなると(N > 5,000,000)、ランタイムは少し低下します。 その理由は明らかです。基数ソートでは、データ全体をコピーする必要があります(実際には、私の単純な実装では2回以上)。これは、メインメモリに最大4 GiBを入れたことを意味します。問題のサイズが実際にはさらに大きくなるため、そうでなかったとしても、これだけのメモリを使用する余裕はありません。 ユースケース 理想的には、このアルゴリズムは、DNAおよびDNA5(追加のワイルドカード文字「N」を許可)、またはIUPAC 曖昧コード(結果として16個の異なる値)を持つDNAの場合でも、2〜100の任意の文字列長で機能する必要があります。しかし、これらすべてのケースをカバーすることはできないので、速度の向上に満足しています。コードは、どのアルゴリズムにディスパッチするかを動的に決定できます。 研究 残念ながら、基数ソートに関するウィキペディアの記事は役に立たない。インプレースバリアントに関するセクションは完全にゴミです。基数ソートのNIST-DADSセクションは、存在しないものの隣にあります。アルゴリズム「MSL」について説明しているEfficient Adaptive In-Place Radix Sortingと呼ばれる有望な論文があります。残念ながら、この論文も残念です。 特に、以下のことがございます。 まず、アルゴリズムにはいくつかの間違いがあり、説明がつかないままです。特に、再帰呼び出しの詳細については説明していません(現在のシフト値とマスク値を計算するためにポインターをインクリメントまたは削減すると単純に想定しています)。また、関数dest_groupを使用し、dest_address定義を行いません。これらを効率的に実装する方法がわかりません(つまり、O(1)で、少なくともdest_address簡単ではありません)。 最後に重要なことですが、アルゴリズムは、配列インデックスを入力配列内の要素と交換することにより、インプレースネスを実現します。これは明らかに数値配列でのみ機能します。文字列に使用する必要があります。もちろん、強い型付けをねじ込むだけで、メモリが属していないインデックスの格納をメモリが許容すると想定して先に進むことができます。しかし、これは、文字列を32ビットのメモリ(32ビット整数と仮定)に押し込める場合にのみ機能します。これはわずか16文字です(現時点では、16> log(5,000,000)であるため無視します)。 著者の1人による別の論文では、正確な説明はまったくありませんが、MSLの実行時間がサブリニアであり、これは完全に間違っています。 要約すると:機能するリファレンス実装、または少なくともDNA文字列で機能する機能するインプレース基数ソートの優れた疑似コード/説明を見つける可能性はありますか?