探索のプログラムについては、既に学習したと思います。
今、例として、次のデータから探索し、外部からの入力値(整数を想定) が、item_in という変数に入ってくるものとします。
DNCL データと入力値の変数
Data=[12,21,26,35,44,50,62,75,83,90]
item_in = 整数値(【外部からの入力】)
線形探索で、データにない値入力への対応
まずは線形探索のほうから。
線形探索とは、初めから順番に、等しい値かどうか調べていく、最も単純な方法です。
DNCL 線形探索
iを0から 要素数(Data)-1まで1ずつ増やしながら繰り返す:
もし Data[i]==item_in ならば:
表示する("[線形探索]: 入力値",item_in,"は添字",i,"番目に見つかった")
ループを抜ける
これを実行し、入力値として90を入れると、次のようになります。
== 実行結果 ==
?90
[線形探索]: 入力値90は添字 9 番目に見つかった
では、もし入力値を、データにない(データ外の) 値 にしたら、どうなるでしょう\(\dotsm\) 。
\(\dotsm\) 何も表示されません。
データ外の値を入れたとき「見つかりませんでした」と答えさせるには、どうすれば良いでしょう。
DNCL データ外に対応のため最後に挿入
iを0から 要素数(Data)-1まで1ずつ増やしながら繰り返す:
もし Data[i]==item_in ならば:
表示する("[線形探索]: 入力値",item_in,"は添字",i,"番目に見つかった")
ループを抜ける
表示する("[線形探索]: 入力値",item_in,"は見つかりませんでした")
ループから出た、最後の行のところに、
いわばこれを入れました。
それで実行してみると
== 実行結果 ==
?89
[線形探索]: 入力値89は見つかりませんでした
うまくいきそうですが、データに ある ような値を入力しても同じように
== 実行結果 ==
?90
[線形探索]: 入力値90は添字 9 番目に見つかった
[線形探索]: 入力値90は見つかりませんでした
\(\dotsm \)「見つかりませんでした」が出てしまいます。
どのようにすればよいでしょうか?。
解決策は、最初の(3)行目のように、初期に真理値を1つおくことです。
DNCL データ外でも機能する線形探索
mitskatta= 偽 #真理値を1つ初期設定
iを0から 要素数(Data)-1まで1ずつ増やしながら繰り返す:
もし Data[i]==item_in ならば:
表示する("[線形探索]: 入力値",item_in,"は添字",i,"番目に見つかった")
mitskatta= 真
ループを抜ける
もし not mitskatta ならば:
表示する("[線形探索]: 入力値",item_in,"は見つかりませんでした")
真理値は「フラグ」とも呼ばれるものです。
初期設定。ループに入る前に定義しておくことで、ループを回した結果、本当に見つかったかどうか、明示することができるようになります。
これを実行させてみると、
== 実行結果 ==
?90
[線形探索]: 入力値90は添字 9 番目に見つかった
?89
[線形探索]: 入力値89は見つかりませんでした
「見つかりませんでした」の表示は、データ内(データにある )値では「見つかる」ので、条件分岐で
表示しないようにし、本当に見つからなかったときだけ 出てくるように、うまくできました。
二分探索とは何だったか 復習から
次は、二分探索です。少し大がかりです。
まずは繰り返し利用できる関数を定義しましょう。
DNCL 一回分の二分探索
関数定義 一回分の探索結果(l, r, test_item):
m = 整数値( (l+r)/2 )
もし test_item == Data[m] ならば:
戻り値 (真, m, m)
もし test_item < Data[m] ならば:
戻り値 (偽, l, m-1)
そうでなければ: #test_item > Data[m] のとき
戻り値 (偽, m+1, r)
ただしデータは、関数の中から閲覧できます。
データから、再掲しておきましょう。はじめ2行にデータが書いてあります。
DNCL 一回分の二分探索まで
Data=[12,21,26,35,44,50,62,75,83,90]
item_in = 整数値(【外部からの入力】)
関数定義 一回分の探索結果(l, r, test_item):
m = 整数値( (l+r)/2 )
もし test_item == Data[m] ならば:
戻り値 (真, m, m)
もし test_item < Data[m] ならば:
戻り値 (偽, l, m-1)
そうでなければ: #test_item > Data[m] のとき
戻り値 (偽, m+1, r)
その続き。この関数を繰り返し利用することで、絞り込み探索を行ないます。
DNCL 一回分の二分探索を使用する
l, r = 0, 要素数(Data)-1
kaisu = 1
ずっと繰り返す:
#戻り値は一つの配列に詰めて返ってくる:
res_Hi = 一回分の探索結果(l, r, item_in)
is_centerleft = res_Hi[0]
l, r = res_Hi[1], res_Hi[2]
もし is_centerleft ならば: # l=r=m
表示する("[二分探索]: 入力値",item_in,"は添字",l,"番目に見つかった")
ループを抜ける
もし l > r ならば: #データにない値を探させるとなる。
表示する("[二分探索]: 入力値",item_in,"は見つかりませんでした")
ループを抜ける
表示する("[二分ログ]: ",kaisu,"回目。入力値のありかは",l,"番目から",r,"番目に絞れる")
kaisu=kaisu+1
これで実行させてみましょう。
二分探索で、データにない値入力への対応は
再掲しておきます。この部分は変える必要はありません。
DNCL 一回分の二分探索まで
Data=[12,21,26,35,44,50,62,75,83,90]
item_in = 整数値(【外部からの入力】)
関数定義 一回分の探索結果(l, r, test_item):
m = 整数値( (l+r)/2 )
もし test_item == Data[m] ならば:
戻り値 (真, m, m)
もし test_item < Data[m] ならば:
戻り値 (偽, l, m-1)
そうでなければ: #test_item > Data[m] のとき
戻り値 (偽, m+1, r)
問題はこの後です。
DNCL 一回分の二分探索を使用する
l, r = 0, 要素数(Data)-1
kaisu = 1
ずっと繰り返す:
#戻り値は一つの配列に詰めて返ってくる:
res_Hi = 一回分の探索結果(l, r, item_in)
is_centerleft = res_Hi[0]
l, r = res_Hi[1], res_Hi[2]
もし is_centerleft ならば: # l=r=m
表示する("[二分探索]: 入力値",item_in,"は添字",l,"番目に見つかった")
ループを抜ける
もし l > r ならば: #データにない値を探させるとなる。
表示する("[二分探索]: 入力値",item_in,"は見つかりませんでした")
ループを抜ける
表示する("[二分ログ]: ",kaisu,"回目。入力値のありかは",l,"番目から",r,"番目に絞れる")
kaisu=kaisu+1
これで実行させると、