===== 番兵法 ===== ==== 線形探索 ==== 線系探索を普通にやろうと思うと、だいたいこうなるよね? 〇 検索するデータ:Key 〇 データ列の数(配列数):N 〇 戻り値:  ・データが見つかった時  :データの位置(index)  ・データが見つからない時 :-1 (Not Foundの戻り値としてあり得ないindexを返す) SequentialSearch() ・ i ← 0  ■ i < N and A[i] != Key  | ・ i ← i + 1  ■  ▲ i => N  | ・ return -1  +---------------  | ・ return i  ▼ Cで書いてみるとこんな感じ #include int main(void){ int n = 5; //配列数 int A[5] = {3, 1, 2, 5, 4}; //C言語ってconst int使えるんだっけ? int i; int Key = 8; //探索する数 printf("Key = %d\n", Key); for (i = 0; i < n; i++) { printf("%d\n", A[i]); if (A[i] == Key) { printf("見つかりました\n"); return 0; } } printf("見つかりませんでした\n"); return 0; } ちなみに、疑似言語通りの動きをする関数を作るとこんな感じ(多分配列を関数に渡す云々とかやってないんだよね?) #include /// /// 大きさnの配列datの中からkeyのデータを探す関数 /// /// 配列のサイズ /// 配列の名前 /// 探すデータ /// /// 戻り値 i:Keyをdat[i]で見つけた。 /// -1:見つからなかった /// int SequentialSearch(int n, int dat[], int key) { int i = 0; while (i < n && dat[i] != key) { i = i + 1; } if (i >= n) return -1; else return i; } int main() { int n = 10; int A[10] = { 6,3,2,9,5,4,10,1,8,7 }; int Key = 8; int res = SequentialSearch(n, A, Key); if (res == -1) printf("not found\n"); else printf("Data is found in A[%02d] = %02d\n", res, A[res]); } はい。改良できるところどこよ?って思うかもしれないですが、ここです。\\ while (i < n && dat[i] != key) (for文で書くとその改良が見えづらいですが)繰り返しの条件が、複合条件で「配列の境界チェック」AND「キーの発見チェック」になっています。\\ 日本語で書くと、\\ **iでループを回すときに「配列が大きさnをオーバーしない、かつ、データの[i]は探しているキーではない」間ループを回す**\\ になっています。逆に言うとループを抜けるのは、「iが配列の大きさnを超えたとき」または、「キーが見つかった時」に配列の添え字を返す関数です。\\ それ以外はエラーとして―1を返します。\\ ここまでは、みんな大丈夫だと思います。\\ ===== 番兵さん ===== この条件をちょい簡単にする方法を考えてみます。\\ やることは簡単で、「必ずどこかでKeyが見つかるようにしておく」です。今のやり方はKeyが見つからないときがあるので、配列よりも添え字がオーバーしちゃわないか\\ こわごわ確認しながらサーチしてます。\\ それを、配列の最大値(最大サーチするとこの次(N+1とする))= Keyにしておくと、 ▲ A[i] == Key | ・ res = i ▼ ▲ i == N | ・ A[0]~A[N-1]までにKeyはなかった(Nまでサーチしちゃってる) +--------------- | ・ A[i]でKeyは見つかった (0~N-1のどこかでKeyを見つけてある) ▼ と書くことができます。つまり、上の疑似言語の「i < N and」がいらなくなるね!\\ このアルゴリズムを、普通の線系探索を参考に疑似言語としてまとめて書いてみます。\\ ==== 番兵さん入り線形探索 ==== 〇 検索するデータ:Key 〇 データ列の数(配列数):N+1 〇 戻り値:  ・データが見つかった時  :データの位置(index)  ・データが見つからない時 :-1 (Not Foundの戻り値としてあり得ないindexを返す) SequentialSearch() ・ i ← 0 ・ A[N] = Key  ■ A[i] != Key  | ・ i ← i + 1  ■  ▲ i == N ?  | ・ return -1  +---------------  | ・ return i  ▼ なんか妙にすっきりしたね笑\\ 最後にソース追加しておくよ\\ #include /// /// 大きさnの配列datの中からkeyのデータを探す関数 /// /// 配列のサイズ /// 配列の名前 /// 探すデータ /// /// 戻り値 i:Keyをdat[i]で見つけた。 /// -1:見つからなかった /// int SequentialSearch(int n, int dat[], int key) { int i = 0; while (i < n && dat[i] != key) { i = i + 1; } if (i >= n) return -1; else return i; } /// /// 大きさnの配列datの中からkeyのデータを探す関数 /// /// 配列のサイズ /// 配列の名前 /// 探すデータ /// /// 戻り値 i:Keyをdat[i]で見つけた。 /// -1:見つからなかった /// int SequentialSearchSentinel(int n, int dat[], int key) { dat[n] = key; //データの最後=配列数と同じインデックスのとこ int i = 0; while (dat[i] != key) { i = i + 1; } if (i == n + 1) return -1; else return i; } int main() { int n = 10; //これはデータ数 //データ数+1の配列が必要 //一番後ろこの場合A[10]は、番兵さんが入るので空けとく int A[11] = { 6,3,2,9,5,4,10,1,8,7 }; int Key = 8; //int res = SequentialSearch(n, A, Key); int res = SequentialSearchSentinel(n, A, Key); if (res == n) printf("not found\n"); else printf("Data is found in A[%02d] = %02d\n", res, A[res]); }