基数ソート

Harshit Jindal 2023年10月12日
  1. 基数ソートアルゴリズム
  2. 基数ソートの例
  3. Radix ソートアルゴリズムの実装
  4. ラディックスソートアルゴリズムの複雑さ
基数ソート
注意
カウントソートが何かわからない場合は、まずカウンティングソートの記事を参照してください。

基数ソートは非比較ソートアルゴリズムです。このアルゴリズムは、基数(Radix/Base は数字を表すのに使われる一意の数字の数です)に従って要素をバケットに挿入することで比較を回避します。例えば、10 進数は 10 桁のユニークな桁数を持ちます)。) 個々の要素の桁数に基づいて要素をソートします。最下位の桁から最上位の桁までの桁数をカウントソートします。バケットソートやデジタルソートとも呼ばれ、並列マシンでは非常に便利です。

基数ソートアルゴリズム

ここでは、n 個の要素を含むソートされていない配列 A[] があるとします。

  • 配列の中で最大の要素 maxm を求めます。
  • maxm の各桁を、安定したソートアルゴリズムを用いて、有効度の低いものから順に並べ替えます。

基数ソートの例

配列 (1851、913、1214、312、111、23、41、9) があるとします。基数ソートアルゴリズムを使用してソートします。

インデックス 入力配列 最初の反復 2 回目の反復 3 回目の反復 4 回目の反復
0 1851 1851 0009 0009 0009
1 0913 0111 0111 0023 0023
2 1214 0041 0312 0041 0041
3 0312 0312 0913 0111 0111
4 0111 0913 1214 1214 0312
5 0023 0023 0023 0312 0913
6 0041 1214 0041 1851 1214
7 0009 0009 1851 0913 1851

最初の繰り返しでは、単位位に基づいてソートし、その後、数十位、数百位、数千位に向かって移動して、最終的なソートされた配列を 9, 23, 41, 111, 312, 913, 1214, 1851 とします。

Radix ソートアルゴリズムの実装

#include <iostream>
using namespace std;
const int N = 10;

int maxm(int arr[], int n) {
  int max = arr[0];
  for (int i = 1; i < n; i++) {
    if (arr[i] > max) {
      max = arr[i];
    }
  }
  return max;
}

void countingSort(int arr[], int n, int place) {
  int output[n];
  int count[N];

  for (int i = 0; i < N; ++i) count[i] = 0;

  for (int i = 0; i < n; i++) count[(arr[i] / place) % 10]++;

  for (int i = 1; i < N; i++) count[i] += count[i - 1];

  for (int i = n - 1; i >= 0; i--) {
    output[count[(arr[i] / place) % 10] - 1] = arr[i];
    count[(arr[i] / place) % 10]--;
  }

  for (int i = 0; i < n; i++) arr[i] = output[i];
}

void radixsort(int arr[], int n) {
  int max = maxm(arr, n);
  for (int place = 1; max / place > 0; place *= 10) countingSort(arr, n, place);
}

int main() {
  int n = 5;
  int arr[5] = {1851, 913, 1214, 312, 111};
  cout << "Input arr: ";
  for (int i = 0; i < n; i++) {
    cout << arr[i] << " ";
  }
  cout << "\n";
  radixsort(arr, n);  // Sort elements in ascending order
  cout << "Output arr: ";
  for (int i = 0; i < n; i++) {
    cout << arr[i] << " ";
  }
  cout << "\n";
}

ラディックスソートアルゴリズムの複雑さ

時間計算量

  • 平均のケース

基数ソートの時間的複雑度は O(n + b) であり、b は入力の範囲です。最大要素 maxmd 桁があるとすると、ラディックスソートの時間複雑度は O(d*(n + b)) となります。d と b は通常小さいので、時間の複雑さは [Big Theta]: O(n) のオーダーです。

  • 最悪のケース

最悪の場合の時間的複雑さは [Big O]:O(n) です。

  • 最良のケース

最良の時間複雑度は [Big Omega]:O(n) です。これは最悪の時間複雑度と同じです。

空間計算量

基数ソートアルゴリズムの空間複雑度は O(n+b) です。ここで b は入力の範囲です。これは、基数ソートの countoutput の配列から来ています。b が n より大きくなることがあり、複雑さが非線形になります。

著者: Harshit Jindal
Harshit Jindal avatar Harshit Jindal avatar

Harshit Jindal has done his Bachelors in Computer Science Engineering(2021) from DTU. He has always been a problem solver and now turned that into his profession. Currently working at M365 Cloud Security team(Torus) on Cloud Security Services and Datacenter Buildout Automation.

LinkedIn

関連記事 - Sort Algorithm