Pythonは二分法検索を実装しています

Pythonは二分法検索を実装しています

二分法は、O(log2n)の時間計算量を持つ比較的効率的な検索方法です。

1から100までの数字があるとします。数字が何であるかを推測できます。推測するたびに、正しい、大きい、または小さいという3つの答えを得ることができます。最小の回数で正しいものを確実に推測するにはどうすればよいですか?多くの人は最初に50を推測することを考えます。推測が大きい場合、答えは50未満で、次に25を推測します...このようにして、1から1までの任意の数について、数値の範囲を毎回半分に減らすことができます。 100.、答えを見つけるのに最大で7回しかかかりません。

毎回検索範囲を半分に減らすこの方法は、二分法検索のアイデアです。この記事では、Pythonを使用して二分検索を実装します。

1.Python二分法検索の再帰的実装

コードを実装する前に、二分法の前提条件を分析します。

1.上記の例では、1から100までの数値を検索し、それが大きいか小さいかを判断するたびに、ここに暗黙の条件があります。つまり、1から100が昇順で配置されます。二分法の場合、データリストは通常​​昇順または降順で並べ替える必要があります。

2. 1〜100の範囲からジャンプします。どのデータセットでも、二分法を使用して特定の数値を検索できます。

次に、二分法検索の特定のプロセスを見てみましょう。たとえば、[50、77、55、29、10、30、66、18、80、51]で77を検索します。

1.リストを並べ替えます。通常、データがソートされることはめったにありません。二分法を使用するには、データリストを最初にソートする必要があります。

2.データの半分を取得します。データセットの場合、データの量は奇数または偶数の場合がありますが、奇数または偶数に関係なく、2で除算されます。

したがって、最初に半分の位置にある50を見つけます。

3.中央の位置の数字と目標の数字のサイズを決定し、検索範囲を狭めてから、手順2を繰り返します。

4.ターゲットデータが見つかるまで、2と3を繰り返します。

検索プロセスによると、コードを実装します。

# coding=utf-8
class BinarySearch(object):
    def binary_search(self, array, data):
        """二分查找法递归实现"""
        if len(array) == 0:
            return False
        array.sort()
        mid_index = len(array) // 2
        if array[mid_index] == data:
            return True
        return self.binary_search(array[mid_index + 1:], data) if data > array[mid_index] else \
            self.binary_search(array[:mid_index], data)

binary_search(array、data):データリスト配列でデータデータを検索します。再帰検索ごとに、データリストの長さが「半分」に短縮されます。ターゲットデータが見つかるか、データリストの長さが0になると、再帰は終了します。

if __name__ == '__main__':
    array = [50, 77, 55, 29, 10, 30, 66, 18, 80, 51]
    search = BinarySearch()
    print('搜索结果:', search.binary_search(array, 77))
    print('搜索结果:', search.binary_search(array, 777))

演算結果:

搜索结果: True
搜索结果: False

2つ目は、Python二分法検索の非再帰的実装です。

二分探索は、非再帰的な方法で実装することも、例として[50、77、55、29、10、30、66、18、80、51]で77を検索することもできます。

1.リストを並べ替えます。

2.データの半分を取得します。ここでは戦略は同じままで、中央の位置のデータが引き続き取得されます。ただし、非再帰的な方法であるため、複数の二分法は循環的な方法でしか実現できません。最初にターゲットデータが見つからない場合、2回目に半分の位置のインデックスを取得するときに、中間インデックスが必要になります。最初の判断の結果に基づいて計算されます。したがって、各二分法の開始インデックスと終了インデックスの終了を記録するには、2つのカーソルを設定する必要があります。ターゲットデータが見つからない場合は、開始インデックスまたは終了インデックスの値を変更して、次のループで中間インデックスを計算します。 。

3.最初のサイクルの判定結果に従って、開始インデックスの値を変更し、中間インデックスを再計算して、中間位置でデータを取得します。

4.ターゲットデータが見つかるまでループを繰り返します。startの値がendの値と等しい場合、範囲は1つのデータのみに縮小されています。ループが継続し、startがendより大きい場合、ターゲットデータが見つからず、ループが終了することを意味します。

このプロセスに従って、コードを実装します。

    def binary_search_normal(self, array, data):
        """二分查找法非递归实现"""
        array.sort()
        start, end = 0, len(array)-1
        while start <= end:
            mid_index = (start + end) // 2
            if array[mid_index] == data:
                return True
            if data > array[mid_index]:
                start = mid_index + 1
            else:
                end = mid_index - 1
        return False

binary_search_normal(array、data):データリスト配列内のデータを検索する非再帰的な実装。各サイクルでは、判定結果に応じて開始値または終了値が変更され、次のサイクルでは、ターゲットデータまたは完全なデータリスト(開始)が見つかるまで、新しい開始値と終了値に従って新しいmin_indexが計算されます。 > end)が見つかり、サイクルが終了します。

    print('搜索结果:', search.binary_search_normal(array, 77))
    print('搜索结果:', search.binary_search_normal(array, 777))

演算結果:

搜索结果: True
搜索结果: False

第三に、二分探索と二分探索木の関係

Pythonでのバイナリ検索ツリーの実装については、https//blog.csdn.net/weixin_43790276/article/details/105753543を参照してください

上記のデータ[50、77、55、29、10、30、66、18、80、51]を二分探索木に追加すると、二分探索木の構造は次のようになります。

二分探索木の特性により、二分探索木にデータを挿入する際に、挿入されたデータとルートノードデータのサイズが最初に判断されます。小さいものは左側のサブツリーに挿入され、大きいものは右のサブツリーに挿入されます。したがって、バイナリ検索ツリーでデータを検索する場合、データのサイズをルートノードのデータサイズと比較し、左のサブツリーと右のサブツリーのどちらで検索するかを再帰的に決定できます。再帰ごとに、ターゲットデータが見つかるまで、スコープが左側のサブツリーまたは右側のサブツリーに絞り込まれます。この検索方法は、二分法検索のアイデアと非常によく似ています。

二分探索木は二分法によって実現されるデータ構造として理解できますが、二分探索木は二分法の概念のみを満たし、二分法とは異なるため、完全に真実ではありません。

データ長は奇数または偶数である可能性があり、二分後の2つのデータセットは等しいか異なるため、二分法はデータ範囲を毎回「半分」減らすことができます。二分探索木では、左右のサブツリーのノード数は加算の順序に依存し、必ずしも同じ数または最大で1つの差を満たすとは限りません。

二分探索木の特性を満たすだけでなく、左右のサブツリー間のノード数の違いを制御するには、二分探索木の「バランス」を制御する必要があります。データ構造では、二分この考えに従って実装されたツリーレッドブラックツリーと呼ばれ、次の記事で引き続き調査します。

 

 

おすすめ

転載: blog.csdn.net/weixin_43790276/article/details/104033516