C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++でカウントソートを使って中央値と最頻値を求める方法

サイズnの配列が与えられたとき、カウントソートの手法を応用して中央値(メジアン)と最頻値(モード)を求めることを考えます。この手法は、配列の要素が限られた範囲内にある場合に特に有効です。例えば、要素が{1, 1, 1, 2, 7, 1}である配列の場合、最頻値は1、中央値は1.5となります。

中央値と最頻値とは

  • 中央値(メジアン):数値を昇順に並べたリストの中央に位置する値
  • 最頻値(モード):リスト内で最も多く出現する要素

求め方の手順

中央値と最頻値を求めるには、以下の手順に従います。

  1. 入力配列のサイズをnと仮定します。
  2. 各値の出現回数を記録するカウント配列を作成します。
  3. カウント配列の中で最大値が格納されているインデックスが、与えられたデータの最頻値となります。
  4. 最大出現回数の要素が複数存在する場合は、そのうちのいずれかを採用できます。
  5. その値をmodeという別の変数に保存します。
  6. 続いて、通常のカウントソートの処理に進みます。累積カウントを計算し、ソート済み配列を構築します。
  7. ソート済み配列において、nが奇数の場合は中央の要素がそのまま中央値になります。nが偶数の場合は中央の2つの要素を取り出し、その平均値を中央値とします。
  8. その値をmedianという別の変数に保存します。

サンプルコード

#include <iostream>
using namespace std;

int main() {
    int arr[] = {1, 1, 1, 2, 7, 1};
    int n = sizeof(arr) / sizeof(arr[0]);

    // 配列内の最大値を求める
    int maxVal = arr[0];
    for (int i = 1; i < n; i++)
        if (arr[i] > maxVal)
            maxVal = arr[i];

    // カウント配列を作成して出現回数を記録
    int count[maxVal + 1] = {0};
    for (int i = 0; i < n; i++)
        count[arr[i]]++;

    // 最頻値を求める
    int mode = 0, maxCount = 0;
    for (int i = 0; i <= maxVal; i++) {
        if (count[i] > maxCount) {
            maxCount = count[i];
            mode = i;
        }
    }

    // カウントソート:累積カウントを計算
    for (int i = 1; i <= maxVal; i++)
        count[i] += count[i - 1];

    // ソート済み配列を構築
    int sorted[n];
    for (int i = n - 1; i >= 0; i--)
        sorted[--count[arr[i]]] = arr[i];

    // 中央値を求める
    double median;
    if (n % 2 == 1)
        median = sorted[n / 2];
    else
        median = (sorted[n / 2 - 1] + sorted[n / 2]) / 2.0;

    cout << "最頻値(モード): " << mode << endl;
    cout << "中央値(メジアン): " << median << endl;

    return 0;
}

出力

最頻値(モード): 1
中央値(メジアン): 1.5

まとめ

このように、カウントソートの考え方を利用すると、要素の範囲が限定された配列から中央値と最頻値をO(n + k)の時間計算量で効率的に求められます(kは要素の最大値)。さらに、ソート済み配列を明示的に構築しなくても、累積カウント配列から中央値の位置を直接特定できるため、メモリ使用量を抑えた実装も可能です。要素の取りうる値の範囲が小さいデータセットを扱う際には、ぜひこの手法を活用してみてください。

  1. C++でカウントソート(計数ソート)を実装する方法

    カウントソートとは カウントソート(計数ソート)は安定なソート手法の一つで、小さな整数値をキーとするデータを並べ替えるために用いられるアルゴリズムです。キー値が同じ要素の個数を数え、その情報をもとに整列を行うのが大きな特徴です。キー同士の差(値の範囲)がそれほど大きくなければ非常に高い効率を発揮しますが、範囲が広すぎる場合は空間計算量が増大する点に注意が必要です。 カウントソートの計算量 時間計算量:O(n+r) 空間計算量:O(n+r) ※ n は要素数、r はキーの最大値(値の範囲)を表します。 入力: ソートされていないデータ列: 2 5 6 2 3 10 3 6 7 8出力: ソー

  2. C++でヒープソートアルゴリズムを使って10個の要素の配列をソートする方法

    ヒープソートは、二分ヒープ(バイナリヒープ)と呼ばれるデータ構造に基づいたソートアルゴリズムです。二分ヒープには2種類あります。最大ヒープでは各親ノードの子ノードが親の値以下になり、最小ヒープでは各親ノードの子ノードが親の値以上になるように構成されます。本記事では、最大ヒープを利用したヒープソートをC++で実装し、10個の要素を持つ配列を昇順に並べ替える手順を詳しく解説します。 ヒープソートの手順(具体例) まず、ソート前の10個の要素からなる元の配列は次の通りです。 207154101590237725 この配列に対してmax-heapify操作を適用し、二分最大ヒープを構築します。配列と