STEP 2.3 (ハッシュ法の基礎)

<問題> 5けたの数 a1a2a3a4a5 (たとえば 67891 ならa1 = 6, a3= 8, a5=1ということ)を、ハッシュ法を用いて配列に格納する。
ハッシュ関数を mod (a1+a2+a3+a4+a5, 23) とし、求めたハッシュ値に対応する位置の配列要素に格納する。

control z (UNIXでは control d ) が入力されるまで5けたのデータを受け付け、配列のどこに格納したのかを示せ。ただし、ハッシュ値が衝突した(かち合いを起こした)場合は、格納しなくてよい。


<実行結果> 

67891(← 入力)
data[8] = 67891(← 格納情報)
1094
data[14] = 1094
55550
data[20] = 55550
54321
data[15] = 54321
5822
data[17] = 5822
3
data[3] = 3
34
data[7] = 34
4631
衝突 (collision) : hash key of 4631  = 14, data[14] is 1094 (← 4631を data[14]には格納できない。衝突の際の処理は、別に作る)

(ここで、control z。すると、配列を一覧)

data[0] = 0
data[1] = 0
data[2] = 0
data[3] = 3
data[4] = 0
data[5] = 0
data[6] = 0
data[7] = 34
data[8] = 67891
data[9] = 0
data[10] = 0
data[11] = 0
data[12] = 0
data[13] = 0
data[14] = 1094
data[15] = 54321
data[16] = 0
data[17] = 5822
data[18] = 0
data[19] = 0
data[20] = 55550
data[21] = 0
data[22] = 0 

<背景>

<プログラム関係>



解答例

#include <stdio.h>
#include <stdlib.h> /* atoiを使う */

#define D 6  /* 5文字(5桁) + \0 */
#define N 23 /* 格納用配列のサイズ */

int main(void) {
    char s[D];  /* D桁の数を、D文字の列としてうけとるための変数 */
    int data[N]; /* N 23で割った余りをハッシュ関数とすると、0-22 */
    int i; /* 配列カウンター用 */
    int k;  /* 計算値 */
    int hk; /* ハッシュ関数値 */

    for (i = 0 ; i < N; i ++) /* データ格納用配列初期化 */
        data[i] = 0;

    for (i = 0 ; i < D; i ++) /* 文字列初期化。0でうめる */
        s[i] = 0;               /* D-1桁の入力を確認すべき */

    while (scanf("%s", s) != EOF) { /* Control zで入力終了 */
        i = 0;
        k = 0;

        while (s[i] != '\0') {  /* 各桁の数を足し算する */
            k = k + s[i] - '0'; /* アスキーコードを使った定番の作戦 */
            i++;
        }

        hk = k % N; /* ハッシュ関数は、5桁の数をa1a2a3a4a5とするとき、mod (a1+a2+a3+a4+a5, N) */

        if (data[hk] == 0) {
            data[hk] = atoi(s); /* 文字列を整数へ型変換 "12345"が、12345になる */
            printf ("data[%d] = %d\n", hk, data[hk]); /* 格納 */
        } else {
            printf ("衝突 (collision) : hash key of %s  = %d, data[%d] is %d \n", s, hk, hk, data[hk]); /* 同じハッシュ値を持つ別のデータが格納済 */
        }


        for (i = 0 ; i < D; i ++)  /* 文字列受け取り用変数を、再初期化 */
            s[i] = 0;
    }

    for (i = 0; i < N; i ++) /* 全データの格納終了。格納状況の一覧表示。0は空いている。*/
        printf("data[%d] = %d \n", i, data[i]);

    return 0;

}