from typing importAny, Sequencedefbin_search(a: Sequence, key: Any) -> int:
a.sort() # 이진 탐색은 정렬된 배열을 탐색할때 가장 빠르다. 받아온 배열을 정렬.
pl = 0# p left 는 인덱스 0 에서 부터 시작
pr = len(a) - 1# p right 는 가장 마지막 인덱스 에서 시작whileTrue:
pc = (pl + pr) // 2# p center은 가운데 인덱스 에서 시작if a[pc] == key: # 검색값이 a배열의 중앙 요소와 같으면return1# 1 반환elif a[pc] < key: # 검색값이 a배열 중앙 요소 보다 작으면
pl = pc + 1# 새로운 p left 인덱스를 중앙인덱스 보다 오른쪽으로 옮겨줌 (우측 탐색)else:
pr = pc - 1# 검색값이 a배열 중앙 요소 보다 크면, 새로운 p right 인덱스를 중앙인덱스 보다 왼쪽으로 옮겨줌 (좌측 탐색)if pl > pr: # p left 인덱스와, p right 인덱스가 교차하면, 배열안에 검색값이 없다는 뜻return0
num = int(input('원소 수를 입력하세요 : '))
x = [None] * num
print('배열 데이터 입력')
for i inrange(num):
x[i] = int(input(f'x[{i}] : '))
ky = int(input('검색 할 값을 입력하세요 : '))
idx = bin_search(x, ky)
if idx == 0:
print('검색값을 갖는 원소가 존재하지 않습니다.')
else:
print(f'검색값이 있습니다.')
이진 탐색의 조건 : 탐색 대상의 데이터가 정렬된 상태여야 한다.
이진 탐색의 종료 조건
1. a[중앙인덱스] == key 일때
2. 검색 범위가 더 이상 없을 경우 : p left 와 p right 가 크로스 될 경우
import copy
defseq_search(seq, key):print("검색 함수 호출됨!")
a = copy.deepcopy(seq)
a.append(key) # 보초키를 추가 (검색할 값을 마지막 인덱스에 추가)print(f'복사되어 보초값 추가된 배열 by.deepcopy : {a}')
k = 0whileTrue: # k 값을 추가 시키면서 탐색 대상 배열 순회# print("seq_search : While Loop 진입")print(f'탐색중인 인덱스 : {k}')
if a[k] == key:
break
k += 1return -1if k == len(seq) else k
# 있으면 해당 값의 인덱스 값을 반환 (배열 길이와 비교하여 나온 값이 보초키값일 경우는 -1 반환)
num = int(input("원소 수를 입력하세요 : "))
x = [None] * num # 원소 수가 num인 배열을 생성for i inrange(num):
x[i] = int(input(f'x[{i}] : '))
ky = int(input('검색할 값을 입력하세요 : '))
idx = seq_search(x, ky)
if idx == -1:
print("검색값을 갖는 원소가 존재하지 않습니다.")
else:
print(f"검색값은 x[{idx}]에 있습니다.")
선형 탐색은 탐색시 마다 2가지 종료 조건을 체크 하게 된다
1. 검색값이 없을 때 : 즉 검색 대상 배열의 끝 도달
2. 검색 값이 있을 때
보초법(Sentinel Method)를 사용하면, 검색할 키값을 대상 배열의 끝에 미리 추가 해둔뒤
원본 검색 대상 배열의 원래 인덱스 크기 보다 검색된 키 값이 있는 배열의 인덱스 크기가 더 크면
검색값이 없는 것으로 취급하는 방법으로 매 탐색 if 분기중 검색값이 없을때를 제외시킴으로 검색 비용을 감소 시킬 수 있다