準備で作成した100万未満のデータが10万個、昇順に整列化されている10万行のファイル data.txtを配列に読み込む。
そのデータに、入力される整数のキーを値にする配列があれば、そのインデックスを示せ。なければ-1を出力せよ
整数が昇順に整列された大きさN(10万)の配列A (data)に整数X (key)があるかを判定する。ある場合は、インデックスを示す。なければ-1を出力する。
入力:配列Aと整数X
出力:配列Aに整数Xがある場合は、インデックスを出力。 ない場合は-1
実行例
key ? : 99732
data[9999] = 99732
key ? : 999998
data[99999] = 999998
key? : 78
-1
<アルゴリズム>
基本的な部分
1. low = 0, high = N-1, mid = (low+high)/2 とする。.5は切り捨てる。 (初期化)
2. low > high なら、終了条件2
3. S[mid] == Key なら、終了条件1
4. そうでないとき、Key < S[mid] ならhigh=mid-1、A[mid] < Key ならlow = mid+1 として、2へ
二分探索をプログラムせよ。(STEP2.4の探索部分を、取り替えなさい)
<ヒント>
解答例 #include <stdio.h> #include <stdlib.h> #include <time.h> #define DATA_SIZE 100000 int main(void) { long data[DATA_SIZE]; long i = 0; FILE *fp; char buffer[16]; long key; long a,b,c; printf("Key? : "); scanf("%ld", &key); fp = fopen("data.txt", "r"); while (fgets(buffer, sizeof (buffer), fp) != NULL) { sscanf(buffer, "%ld", &data[i]); i++; } fclose (fp); /* 以下、二分探索 */ a = 0; b = DATA_SIZE -1; /* 以下、解答 */ while (a <= b) { /* 終了条件2でない間 */ c = (a + b) /2; /* 整数の割り算なので、切り捨て */ if (data[c] == key) { /* 終了条件1 */ printf ("data[%ld] = %ld\n", c, key); break; } else if (data[c] > key) /* cより前にある */ b = c - 1; else if (data[c] < key) /* cより後ろにある */ a = c + 1 ; } if (a > b) /* ループを抜けてきた状態を確認する方法。教科書には、見つけたかどうか、flagを使う方法も、多くみられる */ printf("-1\n"); return 0; }