「大人の教養・知識・気付き」を伸ばすブログ

一流の大人(ビジネスマン、政治家、リーダー…)として知っておきたい、教養・社会動向を意外なところから取り上げ学ぶことで“気付く力”を伸ばすブログです。

MENU

Pythonで学ぶアルゴリズム(07/18)

 アルゴリズムを学ぶのにPythonの学習も兼ねて

を参照していく。

5. データの探索

5.1 配列とデータの探索

################################
### Pythonにおけるデータ探索 ###
################################

import random

random.seed(1) # 乱数シードの設定

my_array = [random.randint(0,100) for i in range(15)] # ランダムな正の整数列を生成

print(my_array) # データの中身を確認

# データを探索
print(32 in my_array) # my_array内に32が存在するか?→論理値
print(my_array.index(17)) #.index(X)でXがリストの何番目(Pythonは0番目から始まる点に注意)にあるかを返す
print(my_array.index(101)) # もし存在しない値を探索させるとValueErrorを返す

5.2 線形探索

 総当たり的にデータの有無を探索するのが線形探索である。そのため計算量は平均的には\displaystyle{\frac{n}{2}}回の比較であり、最悪の場合はn回の比較であるから、\mathcal{O}(n)である。

################
### 線形探索 ###
################

# 総当たり的に値の有無を調べる
def linear_search(array, target):
    for v in array:
        if target == v:
            return True
    return False

print(linear_search(my_array, 17))
print(linear_search(my_array, 101))

5.3 二分探索

 配列がソートされているという前提ではより高速な探索方法が二分探索である。二分探索は以下のようなアルゴリズムを持つ:

  • 配列の真ん中の値をポインタとする。
  • ポインタの値を検索値と比較し、検索値の方が大きければ配列のポインタよりも左側の真ん中を、小さければ右側の真ん中を新たなポインタとする。
  • 検索を再度繰り返し、最終的に残った配列の長さが1となった時点でその値が検索値に一致したらTrue、そうでなければFalseを返す

二分探索の計算量は\mathcal{O}(\log n)である*1。二分探索での結果が\mathrm{False}だったとしても、ポインタの最終的な場所は検索値を検索対象に挿入する場合の場所を表している。

################
### 二分探索 ###
################

import bisect

my_array.sort() # ソートしておく
bisect.bisect(my_array,40)

bisect.bisect_left(my_array,40) # 検索値が存在する場合、目的の値の左側を返す
bisect.bisect_right(my_array,40) # 検索値が存在する場合、目的の値の右側を返す

# Pythonにおけるbisect_rightの実装を引用
def bisect_right(a, x ,lo =0, hi = None):
    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        li = len(a)
    while lo < hi:
        mid = (lo + hi)//2
        if x < a(mid): hi = mid
        else: lo = mid + 1
    return lo

*1:このときの対数の底は2である。

プライバシーポリシー お問い合わせ