昨日までのはこちら
100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて
100日後にエンジニアになるキミ - 53日目 - Git - Gitについて
100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて
100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて
100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1
100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1
100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1
100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1
探索について
プログラミングにおける探索
とは求めるデータを探し出す事です。
データの形もデータの探し方にも色々あります。
線形探索(linear search)
データをリスト
に格納している時はリストの先頭から順番に
リストの最後まで見ていけば欲しいデータが見つかる事でしょう。
このような探索方法を線形探索(linear search)
と言っています。
順番に調べるだけなのでシンプルで実装しやすいです。
次の例は簡単な線形探索の例です。
data=[6342,4588,2362,6812,6102,5119,2631,3548,4559,3570]target=4559flg=False## 線形探索の例
deflinear_search(data,val):forxindata:ifx==val:returnTruereturnFalseprint(linear_search(data,target))
True
比較的わかりやすいアルゴリズムだと思いますが
値が見つかるまで全て調べる必要があるのデータが増えると大変です。
リストの先頭からの順番に数値を探していますが、リストの後方に有ると
かなり時間がかかります。
平均だと$\frac{n + 1}{2}$の比較回数
最悪$O(n)$の処理になってしまいます。
二分探索(binary search)
リストでもデータ数が増えても高速に探し出す方法を考えると線形探索
では難しくなります。
辞書や電話帳のように、ある値を見た際に、目的の値がそれよりも
大きいのか小さいのかで判断する方法として
探索範囲を半分に絞り込むを操作を繰り返すことで高速に探索を行う手法を二分探索
と言っています。
# 二分探索の例
defbinary_search(data,num):left,right=0,len(data)-1whileleft<=right:m=(left+right)//2ifdata[m]==num:returnmelifdata[m]<num:left=m+1else:right=m-1return-1data=[6342,4588,2362,6812,6102,5119,2631,3548,4559,3570]data.sort()print(data)print(binary_search(data,5119))
二分探索
を可能にするにはデータがソートされている必要があります。
探索の前にデータを並び替えておきます。
木構造データの探索(breadth search)
リストに格納されているデータを探索する場面で無く
階層構造になっているデータの中から目的のデータを探し出すとします。
例えばWEBサイトのような木のような構造のデータのなかから
目的のページを探し出すような場合
その際に考えられるのが幅優先探索
と深さ優先探索
です。
幅優先探索(breadth first search)
探索を開始する場所から近いものをリスト化し、それぞれを細かく調べて行く方法を幅優先探索(BFS)
と言います。
# BFS(幅優先探索)
importosfromcollectionsimportdequedefbfs(path):q=deque([])q.append(path)whilelen(q)>0:p=q.popleft()print(p)forchildinos.listdir(p):child_path=p+'/'+childifos.path.isdir(child_path):q.append(child_path)returnqprint(bfs('./'))
深さ優先探索(depth first search)
幅優先探索
に対して目的のほうへ進めるだけ進み、進めなくなったら戻る方法を深さ優先探索(DFS)
と言っています。
バックトラック法
とも呼ばれています。
importosfromcollectionsimportdequedefdfs(path):q=deque([])q.append(path)whilelen(q)>0:p=q.pop()print(p)forchildinos.listdir(p):child_path=p+'/'+childifos.path.isdir(child_path):q.append(child_path)returnqprint(dfs('./'))
まとめ
データの探索方法も多岐にわたり
データの組み方、探し方一つで計算量、実行速度が大きく変わります。
扱うデータに合わせて最適なデータ形式と
探索アルゴリすむを考えてみましょう。
君がエンジニアになるまであと39日
作者の情報
乙pyのHP:
http://www.otupy.net/
Youtube:
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw
Twitter:
https://twitter.com/otupython