サイトマップ / C言語講座出入り口総目次目次:ソート>ビンソート

青い直線

ビンソート

青い直線

[マージソート]←このソース→[ヒープソート]

/* ビンソート */

/* 今日はビンソートについて、学びます。ビン ( bin ) とは、”セサミストリート”でよく見かけるゴミなどを入れておく大きな容器のことです。

ビンソートは、整数の配列で、かつ、配列の要素の値の取る範囲が、前もってわかっている時にしか使えません。例えば、要素数が40で、0から99までの正の整数を取る配列、x[ ] があるとします。値は互いに等しくないとします。

作業用の配列として、要素が100の int 型の配列を用意します。この配列が、ビンソートにおけるデータを一時的にしまう"ビン" になります。Bin[ ] の各要素は、0 に初期化しておきます (注1、2) 。

x[ ] の要素を順番に読んで、Bin[ その値 ] を1インクリメントします。この作業を全ての x[ ] の要素について行った後、Bin[ ] の要素を順番に読んで、Bin[ ] の値が0でなければ、x[ ] に書き戻します。

ビンソートは、ソート対象のデータに制約がありますが、データのばらつきかたに影響されない、高速なソートです。

注1:データがないという意味で、- 1 に初期化する場合もあります。

注2:Bin[ ] は外部変数なので、コンパイル時に、0に初期化されてますが、ビンソートを複数回呼び出すような変更を予想して、呼び出される度に初期化したほうが、安全でしょう。

*/

/* ここからソースプログラム */

#include <stdio.h>

#define MAX_DATA 100
int Bin[MAX_DATA];    /* 作業用配列 */

void BinSort(int x[ ], int n);
void ShowData(int x[ ], int n);
void main(void);

  /* ビンソートを行う */
void BinSort(int x[ ], int n)
{
    int i, j;
	
    if (n > MAX_DATA) {
        printf("データが多すぎます!\n");
        return;
    }
    else {
        for (i = 0; i < MAX_DATA; i++)
            Bin[i] = 0;             /* 作業用配列の初期化 */

        for (i = 0; i < n; i++)     /* x[i] の値の */
            Bin[x[i]]++;            /* Bin[ ] の要素の値を */
                                    /* インクリメント */
        j = 0;                      /* x[ ] の添字として使用 */
        for (i = 0; i < MAX_DATA ; i++) 
            if (Bin[i])             /* 0でなければ */
            x[j++] = i;             /* 書き戻す */
    }
}

  /* n 個のデータを表示する */
void ShowData(int x[ ], int n)
{
    int i;

    for (i = 0; i < n ; i++)
        printf("%d\t", x[i]);
}


void main(void)
{
      /* ソートするデータ */
    int x[MAX_DATA] = {89, 1, 78, 58, 48, 18, 9, 21, 56, 11, 
                       62, 23, 38, 96, 4, 45, 73,14, 30, 27,
                        6, 35, 2, 25, 69, 41, 8, 51, 0, 32,
                       98, 12, 33, 72, 19, 52, 28, 86, 17, 99
    };
    int n = 40;     /* ソートするデータの数 */

      /* ソート前のデータを表示 */
    printf("ソート前:\n");
    ShowData(x, n);
    printf("\n");

    BinSort(x, n);
		
      /* ソート後のデータを表示 */
    printf("\n\nAソート後:\n");
    ShowData(x, n);
}

/* ここまでソースプログラム */

/* ビンソートの欠点として、配列の取りうる値の範囲が広いと、メモリ効率が悪くなり、更に広いと、作業用の配列を事実上取れなくなります。例えば、0から100,000 までの値を取りうる、要素数 10 の配列のソートなどが、これに当たります。

実は、以前に、ビンソートの文字版について学んでいます( ファイル中の英文字の出現頻度を調べる ) 。これは char のサイズの数の要素を持った配列を用意して、ファイルの中で現れるアルファベットの値を添字として使い、その配列の要素をインクリメントして、アルファベットの出現頻度を調べるプログラムです。 */

[マージソート]←このソース→[ヒープソート]

青い直線

/* (C) 2000- YFプロ. All Rights Reserved. */    提供:C言語講座−それ自体コンパイルできる教材を使った講座です−

青い直線

サイトマップ / C言語講座出入り口総目次目次:ソート>ビンソート