カーディナリティの並べ替え
カーディナリティソートは、カウントソートのアプリケーション拡張であり、割り当てソートの特殊なケースです。カウントソート(バケットソート)は、小数の範囲でのソートに適していますが、大きな数値には効率的ではありません。・基数の性質を利用し、16進数の範囲内で多数を10進数に分解し、複数回カウント等の安定したソートを行い、多数の範囲内でのソート機能を実現します。
たとえば、2桁間の並べ替えの問題の場合、通常は10桁から始め、同じ桁を10桁と比較してから、桁を比較し、最終的に目的の結果を取得します。基本的な並べ替えのプロセスはほぼ同じです。違いは、数十または同じ数の場合、カウントソートプロセスを使用します。中央の要素を比較する必要はありません。
カーディナリティの並べ替えは、最上位桁優先方式(MSD)と最下位桁優先方式(LSD)に分けられます。コンピューターが高優先順位方式を実装する場合、再帰的な分割統治であるバケットスペースの割り当てをネストする必要があります。アルゴリズムの実行はより複雑であるため、LSDの実装がより一般的です。
LSD配列ベースの実装コードは次のとおりです。
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
int[] arr = new int[] { 97, 53, 88, 59, 26, 41, 88, 31, 22 };
arr = radixSort(arr, 9, 2, 10);
System.out.println(Arrays.toString(arr));
}
/**
*
* @param array 排序序列
* @param n 排序序列元素数
* @param d 排序位数(两位数传入2)
* @param r 基
*/
public static int[] radixSort(int[] array, int n, int d, int r) {
// 内部桶排序时用以保存各桶中的元素数
int[] count = new int[r];
// 按照不同基位进行桶排序时存放元素
int[] tmpArray = new int[n];
// 模除数,计算桶位
int radix = 1;
// 临时变量,用于计算每个元素的桶位,避免重复声明
int k = 0;
// 进行d轮计数排序(/桶排序)
for (int i = 0; i < d; i++) {
// 每轮循环,须重新初始化count数组
for (int j = 0; j < r; j++) {
count[j] = 0;
}
// 遍历原始数组,计算每个桶位的元素数,存储于count数组
for (int j = 0; j < n; j++) {
k = (array[j] / radix) % r;
count[k]++;
}
// 计数器对应位数值修改为下一位的开始位置
for (int j = 1; j < r; j++) {
count[j] = count[j] + count[j - 1];
}
// 进行桶排序过程
for (int j = n - 1; j >= 0; j--) {
// 计算元素桶位
k = (array[j] / radix) % r;
count[k]--;
tmpArray[count[k]] = array[j];
}
// 回写到原数组
for (int j = 0; j < n; j++) {
array[j] = tmpArray[j];
}
// 基位递增
radix *= r;
}
return array;
}
}
まとめ
基数ソートの主な考え方は、基数に従ってソートされた要素を分割することです。分割後の各値は16進数の値に属します。これに基づいて、バケットのソートは各桁に従って実行されます。これは、直感的な理解とは異なります。再帰的な分割統治アルゴリズムを処理する場合、コンピューターはより複雑になるため、一般的な実装はLSDの低い優先度のアルゴリズムです。少し考慮すると、高優先度のMSDと低優先度のLSDの直観的な違いは、並べ替えの処理方向が異なることだけです。
推奨情報:
Radix sort-Wikiwand
詳細については、私の公開アカウントに注目してください。