2分探索は、小さい順に並んだ配列から目当ての値を探すやり方です。まん中の1つと比べるたびに、探す範囲が半分になります。
期間限定クーポンPR|Udemy の講座科目B オリジナル模試 3回分・60問42%OFF 1,500円第2部 定番処理の型 全26回A7-12分探索一覧を開く
A1-1トレース表の書き方A1-2繰返しのトレースA1-3配列のトレースA2-1配列を全部見るA2-2最大・最小を見つけるA2-3探す(線形探索)A2-4入れる・消すA3-12次元配列の走査A3-22次元配列の集計A4-1文字列を1文字ずつA4-2文字列照合A5-1交換して並べるA5-2挿入ソートA6分割して並べるA7-12分探索A7-2ハッシュ表探索A8-1再帰とはA8-2再帰のトレースA9スタックとキューA10-1リストを読むA10-2リストの挿入と削除A11木構造A12木の巡回A13グラフA14AI・データを題材にしたプログラムA15コントロールブレーク処理
この回の内容を動画で見る
次のページで講義の目次と無料の講義を見られます。受講ボタンとクーポンコードもそこにあります。
この回の内容を動画で見る
解くための再現性が身につく講義29本小テスト86問模試3回分IT資格の森で見る
講義「2分探索」(全7分50秒)は、IT資格の森(月額1,280円)の会員向けです。科目Bは、1行ずつ値を追うアニメの講義と、講義ごとの小テスト、本番と同じ形の模擬試験がそろっています。
2分探索とは ── まん中と比べて、半分を捨てる
6個の値が小さい順に並んだ配列から、47 が何番目にあるかを探します。見るのは毎回、探す範囲のまん中の1つだけです。
47 を探す ── 1回比べるたびに、探す範囲が半分になる
整数型の配列: data ← {11, 23, 35, 47, 59, 62} / ▲=いま比べている、まん中の枡 / 下の3つの箱=探す範囲の左端・右端と、まん中が何番か / 灰色の枡=47 は無いと分かって、もう見ない枡 / 緑の枡=探している値と同じだった枡
1回目 探す範囲は 1〜6番
data
111
223
335▲
447
559
662
左端1
右端6
まん中3
まん中は (1 + 6) ÷ 2 = 3.5、小数を切り捨てて 3番。3番の 35 は 47 より小さい。小さい順に並んでいるので、3番から左はどれも 35 以下 ── 47 は 1〜3番には無い。左端を 4 にする。
2回目 探す範囲は 4〜6番
data
111
223
335
447
559▲
662
左端4
右端6
まん中5
まん中は (4 + 6) ÷ 2 = 5 で 5番。5番の 59 は 47 より大きい。5番から右はどれも 59 以上 ── 47 は 5〜6番には無い。右端を 4 にする。
3回目 探す範囲は 4番だけ
data
111
223
335
447▲
559
662
左端4
右端4
まん中4
まん中は (4 + 4) ÷ 2 = 4 で 4番。4番の 47 は、探している 47 と同じ。見つかった ── 答えは 4(番目)。
6個の中から、まん中を3回見ただけで見つかった。
毎回やることは同じです。
まん中の値が、探している値より…
小さい ── まん中から左には無い。左端を、まん中の1つ右へ動かす
大きい ── まん中から右には無い。右端を、まん中の1つ左へ動かす
同じ ── 見つかった。まん中の番号が答え
1回比べるたびに範囲が半分になるので、配列が大きくても比べる回数は少なくて済みます。1000個あっても、1000 → 500 → 250 → … と半分にするのを10回ほどくり返せば、残りは1個です。前から1つずつ比べていく線形探索だと、目当ての値が最後にあれば1000回かかります。
並んでいることが前提
まん中の1つを見ただけで半分を捨てられるのは、配列が小さい順に並んでいるからです。並んでいない配列で同じことをすると、こうなります。
並んでいない配列で同じことをすると、捨てた半分に 47 が残る
整数型の配列: data ← {62, 47, 35, 11, 59, 23}(小さい順に並んでいない) / ▲=まん中の枡 / 灰色の枡=捨てた枡 / 枠に色の付いた枡=47 がある枡
1回目 まん中は 3番の 35。47 より小さいので、1〜3番を捨てる
162
247
335▲
411
559
623
ところが 47 は、捨てた 2番にあった
162
247
335
411
559
623
このあと 4〜6番をいくら探しても 47 は出てこない。配列の中にあるのに「無い」と答えてしまう。
小さい順に並んでいることを昇順といいます。この探し方を使うプログラムは、配列が昇順に並んでいることを前提にしています。
基本情報技術者試験 科目B サンプル問題 問13 の関数 search は、この探し方で配列 data から値を探します。問題文には「data は昇順に整列されており,値に重複はない。」と書かれています。「昇順に整列されており」は、小さい順に並べてあるという意味です。「重複はない」は、同じ値が2つ入っていないという意味です。だから、答えの要素番号は1つに決まります。なお、出題の search には不具合が1つ入れてあり、それを見つける問題になっています。
プログラムを、上から読む
ここまでの手順を関数にしたものです。配列 data と探す値 target を受け取り、見つかればその要素番号(何番目か)を、見つからなければ -1 を返します。47 を探した図の「左端」「右端」「まん中」が、変数 low・high・middle です。
○整数型: nibunTansaku(整数型の配列: data, 整数型: target)
整数型: low, high, middle
low ← 1
high ← dataの要素数
while (low ≦ high)
middle ← (low + high) ÷ 2 の商
if (data[middle] < target)
low ← middle + 1
elseif (data[middle] > target)
high ← middle - 1
else
return middle
endif
endwhile
return -1
当サイトで作った例です。
data が {11, 23, 35, 47, 59, 62}、target が 47 なら、47 を探した図のとおり、まん中を3回見て 4 を返します。
上から読む
-
○整数型: nibunTansaku(整数型の配列: data, 整数型: target)
関数の宣言。整数型の配列と整数を1つずつ受け取り、整数型の値を返す関数です。要素番号は 1 から数えます(サンプル問題 問13 の問題文にも「配列の要素番号は1 から始まる。」とあります)。 -
整数型: low, high, middle low ← 1 high ← dataの要素数
探す範囲の両端。lowが左端、highが右端の要素番号です。はじめは配列の全体なので、1 と、dataに入っている値の個数(dataの要素数)を入れます。 -
while (low ≦ high)
範囲に1つでも残っているあいだ、くり返す。whileは、かっこの中が成り立つあいだendwhileまでをくり返します。≦は「以下」です。lowとhighが同じなら、残りは1個です。 -
middle ← (low + high) ÷ 2 の商
まん中の番号を決める。÷ 2 の商は、2で割った答えの整数の部分です。(1 + 6) ÷ 2は 3.5 なので、商は 3 になります。 -
if (data[middle] < target) low ← middle + 1 elseif (data[middle] > target) high ← middle - 1半分を捨てる。data[middle]は、dataのmiddle番目の値 ── まん中の値です。ifからendifまでは、上からif、elseifの順に条件を見て、最初に成り立った1か所だけを実行します。まん中の値のほうが小さければ左端を、大きければ右端を動かします。middle番はいま見て「ちがう」と分かったので、+ 1・- 1をして範囲から外します。 -
else return middle endif見つかった。elseは、上のどの条件も成り立たなかったときに実行されます。小さくも大きくもないなら、同じ値です。return middleはmiddleの値(まん中の番号)を返して、くり返しの途中でも関数を終わります。 -
endwhile return -1
最後まで無かったとき。whileを抜けるとreturn -1の行に来ます。要素番号は 1 からなので、-1 は番号としてありえない値 ── 呼んだ側は「無かった」と判断できます。
終わり方は2つ ── 見つかったとき、範囲が空になったとき
この関数が終わる場所
見つかった ── まん中の値が target と同じだった。return middle で終わる
範囲が空 ── low ≦ high が成り立たなくなって while を抜けた。return -1 で終わる
1つ目は、47 を探した図の3回目です。middle が 4 で、data[4] が 47 と同じなので、return middle で 4 を返します。2つ目を、同じ配列で入っていない値 20 を探して確かめます。
入っていない値 20 を探す
当サイトオリジナルの例題
ループ開始前
配列
いま計算していること
変数の状態
return で返した値
トレース表(進めると1行ずつ積み上がります)
左端が右端より右に来たら、範囲には1つも残っていません。だから while を抜けて、-1 を返します。
くり返しのたびに、middle 番は必ず範囲から外れます。範囲は毎回1つ以上せまくなるので、見つからない場合もいつかは空になり、くり返しは終わります。
次に読む
| A7-2 | ハッシュ表探索 ─ 入れる場所を計算で決める |
| A2-3 | 線形探索 ─ 前から1つずつ照らし合わせる |
| 問13 | サンプル問題 問13の解説 ─ この探し方の関数 search から不具合を見つける問題 |
| 目次 | 基本情報技術者試験 科目B 攻略ガイド |
この記事で引用した資料
いずれも独立行政法人情報処理推進機構(IPA)が公表したものです。IPAは公表済みの試験問題について、教育目的での使用に許諾および使用料を不要としていますが、著作権は放棄していません。本記事では、引用した箇所の文言を改変していません(省略や補いがある場合は、その場に明記しています)。
本文の例題とプログラムは当サイトのオリジナルです。


