0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

数値を線形探索/2分探索で探してみよう

Last updated at Posted at 2020-10-12

こんにちは。
いつも応援有難うございます m(_ _)m
9/23 から投稿を開始して、そろそろ 3 週間が経とうとしています。
楽しいことは あっ という間ですね(笑)。

さて、今回は探索です。
最初は線形探索から行きましょう。
構えなくて大丈夫です。
図1.PNG
こんな感じで左から順番に、探したい値と赤字が一致しているか確認するだけです。
※すいません、途中で図が切れてて。。
早速、書いてみましょう。

linear_search.py
def search(x,key):
    
    for i in range(len(x)):
        if x[i] == key:
            print(f"value is placed at x[{i}]")
            break
 #最終項 x[6] != key の場合、前述の if x[i] == key を pass するので、
 #そのまま以下の if 文に入ります。
 #i == len(x)-1 なら、fail です。
        if i == len(x)-1:
            print("fail to serch")
            break


if __name__ == "__main__":
    x = [6,4,3,2,1,2,8]                      # 配列を指定
    key = int(input("enter search value: ")) # 探したい値を入力
    search(x,key)

では次は、2分探索です。
線形探索との前提条件が大きく異なります。その違いをイメージにしました。
図2.PNG
線形探索の場合は、与えられたものを端から比較していくのですが、
2分探索は、そうは行きません。一旦、整列します。出だしが全然違うので注意が必要です。
(? _ ?)(? _ ?)(?_?)
はい、構わず次のステップに行きます。
図3.PNG
仮に 3 を探している場合、中央値との比較で一発で発見できます(笑)
では、3 より小さい値を探している場合はどうでしょうか。
図4.PNG
探したい値が1の場合どうしましょうか。
[1 , 2 , 2] の中央値 2 でもない場合は、更にそれ以下の
1 が格納されている x[0] を見るだけです。
もし、それでも探している値が無ければ、探し物はそもそも、
用意された配列には存在しない事になります。
一旦、整理しないとイケないメンドイ アルゴですが、なかなか有名らしいです。
今回は再帰で書いてみました。

binary_search.py
def binary_search(x,left,right,key):
    cen = (left + right)//2
    if left > right:
        print(f"left is {left},right is {right}")
        print("faile to search")
        return None
    if x[cen] == key:
        return print(f"found at x[{cen}]")

    #中央値 x[cen] が探し物 key より大きい場合
    if x[cen] > key:
        print(f"left is {left},cen is {cen}")
        binary_search(x,left,cen-1,key)#cen-1 の "-1" がミソです!!!

    #中央値 x[cen] が探し物 key より小さい場合
    if x[cen] < key:
        print(f"cen is {cen},right is {right}")
        binary_search(x,cen+1,right,key)#cen+1 の "+1" がミソです!!!
    
if __name__ == "__main__":
    x =[1,2,2,3,4,6,8]
    
    binary_search(x,0,len(x)-1,1)
実行結果.py
left is 0,cen is 3
left is 0,cen is 1
found at x[0]

左側を選択し、徐々に狭めていますね。
配列長を大きくしてイメージを作り直してみました。
このほうが分かりやすいかもしれません(中央値は赤、探し物が 7 の場合)。
図5.PNG
もし、探し物が7じゃなかったらどうしますか?
以下の記述のミソに着目してみてください。

miso.py
    #中央値 x[cen] が探し物 key より大きい場合
    if x[cen] > key:
        print(f"left is {left},cen is {cen}")
        binary_search(x,left,cen-1,key)#cen-1 の "-1" がミソです!!!

    #中央値 x[cen] が探し物 key より小さい場合
    if x[cen] < key:
        print(f"cen is {cen},right is {right}")
        binary_search(x,cen+1,right,key)#cen+1 の "+1" がミソです!!!

念のため実行してみると以下のコメントが見えてきます。

実行結果.py
left is 5,right is 4 
faile to search

そうなんです。left > right が実現しています。
どういう事でしょうか?

探し物が 6 だった場合、
記述にある **if x[cen] > key:**に突入します。

その結果、binary_search(x,left,cen-1,key) となります。
この時点で、left == right なので、前述の式を考えると
left > right になりますよね!??。
これが逆転の仕組みです。
ここまで来たら、何もないって言えますよね??
※逆のパターン(if x[cen] < key:)もしかりです(≧▽≦)

もっとシンプルに書ける方が居たら、
申し訳ありませんが御教示宜しくお願い致します。m(_ _)m

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?