C++で基数ソート(ラディックスソート)を実装するプログラム
基数ソート(ラディックスソート)は、非比較型のソートアルゴリズムの一つです。要素同士を直接比較するのではなく、整数キーを構成する各桁に注目し、同じ桁位置・同じ値を持つ数字どうしをグループ化しながら並べ替えを行います。
「基数」とは記数法における底のことです。私たちが普段使う10進法では基数は10であるため、10進数を基数ソートで並べ替える際には、数値を一時的に格納するための10個のバケット(ポケット)が必要になります。
基数ソートの計算量
時間計算量: O(nk) ※nは要素数、kは最大桁数
空間計算量: O(n+k)
入力 − ソート前のデータ: 802 630 20 745 52 300 612 932 78 187 出力 − ソート後のデータ: 20 52 78 187 300 612 630 745 802 932
アルゴリズム
radixSort(array, size, maxDigit)
入力: データの配列、配列内の要素の総数、最大値の桁数。
出力: ソート済みの配列。
Begin
10個のリストを pocket として定義する
for i := 0 to max -1 do
m = 10<sup>i+1</sup>
p := 10<sup>i</sup>
for j := 0 to n-1 do
temp := array[j] mod m
index := temp / p
pocket[index].append(array[j])
done
count := 0
for j := 0 to radix do
while pocket[j] が空でない間
array[count] := pocket[j] の先頭ノードを取り出して削除
count := count +1
done
done
End
このアルゴリズムでは、まず最下位の桁(1の位)から順に着目し、その桁の値に応じて各要素を対応するバケットへ振り分けます。その後、バケット0から9の順に要素を元の配列へ戻す操作を、上位の桁について繰り返します。この処理を最大桁数ぶん行うことで、配列全体が昇順に整列されます。
サンプルコード
#include<iostream>
#include<list>
#include<cmath>
using namespace std;
void display(int *array, int size) {
for(int i = 0; i<size; i++)
cout << array[i] << " ";
cout << endl;
}
void radixSort(int *arr, int n, int max) {
int i, j, m, p = 1, index, temp, count = 0;
list<int> pocket[10]; // 10進数の基数は10
for(i = 0; i< max; i++) {
m = pow(10, i+1);
p = pow(10, i);
for(j = 0; j<n; j++) {
temp = arr[j]%m;
index = temp/p; // バケット配列のインデックスを求める
pocket[index].push_back(arr[j]);
}
count = 0;
for(j = 0; j<10; j++) {
// リンクリストから削除しながら配列へ格納し直す
while(!pocket[j].empty()) {
arr[count] = *(pocket[j].begin());
pocket[j].erase(pocket[j].begin());
count++;
}
}
}
}
int main() {
int n, max;
cout << "要素数を入力してください: ";
cin >> n;
cout << "要素の最大桁数を入力してください: ";
cin >> max;
int arr[n]; // 指定された要素数で配列を作成
cout << "要素を入力してください:" << endl;
for(int i = 0; i<n; i++) {
cin >> arr[i];
}
cout << "ソート前のデータ: ";
display(arr, n);
radixSort(arr, n, max);
cout << "ソート後のデータ: ";
display(arr, n);
}
実行結果
要素数を入力してください: 10 要素の最大桁数を入力してください: 3 要素を入力してください: 802 630 20 745 52 300 612 932 78 187 ソート前のデータ: 802 630 20 745 52 300 612 932 78 187 ソート後のデータ: 20 52 78 187 300 612 630 745 802 932
このように、基数ソートはクイックソートやマージソートのような比較ベースのソートとは異なり、桁ごとの振り分けだけで整列を行える点が大きな特徴です。特に、桁数kが小さく要素数nが多い整数データに対しては、O(nk)という効率的な性能を発揮します。
-
C++でバケットソートを実装する方法【アルゴリズムとサンプルコードを解説】
バケットソートとはバケットソート(Bucket Sort)は、データ要素を複数の「バケット(桶)」に分配してから整列を行うソート手法です。各バケットには性質の似たデータが格納され、分配後は各バケット内を別のソートアルゴリズム(ここでは標準ライブラリの sort)で整列します。最後にすべてのバケットの要素を元の配列へ順番に集めることで、全体がソートされた状態になります。このアルゴリズムは、入力データが0.0以上1.0未満のような一様な分布に従う場合に特に高い性能を発揮します。バケットソートの計算量時間計算量: 最良ケース・平均ケースで O(n + k)、最悪ケースで O(n²)空間計算量: 最悪
-
C++でクイックソートを実装するプログラム|ランダム化で最悪ケースO(n²)を回避
クイックソート(Quick Sort)は「分割統治法(divide-and-conquer)」に基づく高速な整列アルゴリズムです。平均時間計算量は O(n log n) と非常に効率的ですが、ピボットの選び方次第では最悪ケースで O(n²) まで計算量が悪化する可能性があります。 そこで本記事では、乱数を用いてピボットをランダムに選択する「ランダム化クイックソート」をC++で実装し、最悪ケースが発生する確率を大幅に下げる方法を解説します。 アルゴリズム Partition(int a[], int l, int h) 配列 a の範囲 [l, h] を、ピボットより小さいグループと大きい