파이썬에는 명시적인 이진 검색 알고리즘이 없지만 이진 검색을 bisect
사용하여 정렬 된 목록에서 요소의 삽입 지점을 찾도록 설계된 모듈이 있습니다. 이진 검색을 수행하는 데 "속임수"가있을 수 있습니다. 이것의 가장 큰 장점은 대부분의 라이브러리 코드와 동일한 이점입니다. 성능이 뛰어나고 잘 테스트되었으며 작동합니다 (특히 이진 검색은 성공적으로 구현하기 가 매우 어려울 수 있습니다) -특히 엣지 케이스를 신중하게 고려하지 않는 경우).
기본 유형
Strings 또는 int와 같은 기본 유형의 경우 매우 쉽습니다. bisect
모듈과 정렬 된 목록 만 있으면 됩니다.
>>> import bisect
>>> names = ['bender', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> bisect.bisect_left(names, 'fry')
1
>>> keyword = 'fry'
>>> x = bisect.bisect_left(names, keyword)
>>> names[x] == keyword
True
>>> keyword = 'arnie'
>>> x = bisect.bisect_left(names, keyword)
>>> names[x] == keyword
False
이것을 사용하여 중복을 찾을 수도 있습니다.
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
분명히 원하는 경우 해당 색인의 값 대신 색인을 반환 할 수 있습니다.
사물
사용자 정의 유형 또는 객체의 경우 상황이 약간 까다로워집니다. 이등분을 올바르게 비교하려면 풍부한 비교 방법을 구현해야합니다.
>>> import bisect
>>> class Tag(object): # a simple wrapper around strings
... def __init__(self, tag):
... self.tag = tag
... def __lt__(self, other):
... return self.tag < other.tag
... def __gt__(self, other):
... return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
이것은 적어도 Python 2.7-> 3.3에서 작동해야합니다.