-
Notifications
You must be signed in to change notification settings - Fork 0
/
2. binary_search.py
132 lines (109 loc) · 4.38 KB
/
2. binary_search.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""
이진 탐색 (Binary Search)
정렬된 리스트에서 특정 값의 위치를 찾는 알고리즘. 처음 중간의 값을 임의의 값으로 선택하여,
그 값과 찾고자 하는 값의 크고 작음을 비교하는 방식을 채택하고 있다.
처음 선택한 중앙값이 만약 찾는 값보다 크면 그 값은 새로운 최댓값이 되며, 작으면 그 값은 새로운 최솟값이 된다.
검색 원리상 정렬된 리스트에만 사용할 수 있다는 단점이 있지만,
검색이 반복될 때마다 목표값을 찾을 확률은 두 배가 되므로 속도가 빠르다는 장점이 있다.
"""
from __future__ import print_function
import bisect
try:
raw_input # Python 2
except NameError:
raw_input = input # Python 3
#이진탐색
def binary_search(sorted_collection, item):
"""
input값은 반드시 정렬 된 채로 주어져야 합니다.
그러지 않으면 원하지 않는 결과값이 나올 수 있습니다.
:param sorted_collection : 탐색을 진행할 배열
:param item : 탐색을 진행할 키(key) 값
:return : 키 값이 있는 위치(index), 없을 경우 None
예시:
>>> binary_search([0, 5, 7, 10, 15], 0)
0
>>> binary_search([0, 5, 7, 10, 15], 15)
4
>>> binary_search([0, 5, 7, 10, 15], 5)
1
>>> binary_search([0, 5, 7, 10, 15], 6)
"""
left = 0
right = len(sorted_collection) - 1
while left <= right:
midpoint = (left + right) // 2
current_item = sorted_collection[midpoint]
if current_item == item:
return midpoint
else:
if item < current_item:
right = midpoint - 1
else:
left = midpoint + 1
return None
#라이브러리 내장함수를 이용한 이진탐색
def binary_search_std_lib(sorted_collection, item):
index = bisect.bisect_left(sorted_collection, item)
if index != len(sorted_collection) and sorted_collection[index] == item:
return index
return None
#재귀를 이용한 이진탐색
def binary_search_by_recursion(sorted_collection, item, left, right):
"""
가장 처음 재귀는 left = 0, right=(len(sorted_collection)-1)을 초기값으로 줘야합니다.
:param left : 탐색 범위의 시작
:param right : 탐색 범위의 끝
"""
if (right < left):
return None
midpoint = left + (right - left) // 2
if sorted_collection[midpoint] == item:
return midpoint
elif sorted_collection[midpoint] > item:
return binary_search_by_recursion(sorted_collection, item, left, midpoint-1)
else:
return binary_search_by_recursion(sorted_collection, item, midpoint+1, right)
#입력값이 정렬이 됬는지 확인 해주는 함수
def __assert_sorted(collection):
"""
:param collection : 입력 값
;return : 정렬이 되어있으면 True값 반환, 아니면 error 발생
예시:
>>> __assert_sorted([0, 1, 2, 4])
True
>>> __assert_sorted([10, -1, 5])
error: Collection must be sorted!
"""
if collection != sorted(collection):
print('error: Collection must be sorted')
raise ValueError('Collection must be sorted')
return True
if __name__ == '__main__':
import sys
user_input = raw_input('Enter numbers separated by comma:\n').strip()
collection = [int(item) for item in user_input.split(',')]
try:
__assert_sorted(collection)
except ValueError:
sys.exit('Sequence must be sorted to apply binary search')
target_input = raw_input('Enter a single number to be found in the list:\n')
target = int(target_input)
#binary_search 함수 사용
result = binary_search(collection, target)
if result is not None:
print('{} binart search found at positions: {}'.format(target, result))
else:
print('Not found')
#binary_search_std_lib 함수 사용
result = binary_search_std_lib(collection, target)
if result is not None:
print('{} binart search by library found at positions: {}'.format(target, result))
else:
print('Not found')
#binary_search_by_recursion 함수 사용
result = binary_search_by_recursion(collection, target, 0, len(collection)-1)
if result is not None:
print('{} binary search by recursion found at positions: {}'.format(target, result))
else:
print('Not found')