정렬된 리스트에서 원하는 값의 존재 여부 또는 위치를 빠르게 찾는 알고리즘
O(log N)N일 때, 최악의 경우 N번 비교O(N)O(log N)target이 중간값보다 작으면 왼쪽 절반 탐색이 방식은 분할 정복(Divide and Conquer) 알고리즘에 속한다
예) 숫자 맞추기 게임에서 항상 중간값을 선택하면 최소 시도로 정답을 찾을 수 있다
#include <iostream>
#include <vector>
using namespace std;
vector<int> numbers;
void BinarySearch(int N)
{
int left = 0;
int right = (int)numbers.size() - 1;
while (left <= right)
{
cout << "탐색 범위 : " << left << "~" << right << endl;
// 중간값 계산 (오버플로우 방지)
int mid = left + (right - left) / 2;
if (N < numbers[mid])
{
right = mid - 1;
}
else if (N > numbers[mid])
{
left = mid + 1;
}
else
{
cout << "값 " << N << "을(를) 찾았습니다! 인덱스: " << mid << endl;
return;
}
}
cout << "값 " << N << "은 배열에 없습니다." << endl;
}
int main()
{
numbers = vector<int>{ 1, 8, 15, 23, 32, 44, 56, 63, 81, 91 };
BinarySearch(82);
return 0;
}
탐색 범위 : 0~9
탐색 범위 : 5~9
탐색 범위 : 8~9
탐색 범위 : 9~9
값 82은 배열에 없습니다.
82는 32, 63, 81, 91과 비교되며, 그때그때 탐색 범위가 반씩 줄어든다left > right가 되어 탐색이 종료된다| 항목 | 배열 | 트리 |
|---|---|---|
| 삽입/삭제 성능 | 느림 (정렬 유지 필요) | 빠름 (동적 구조) |
| 이진 탐색 가능 | 가능 (정렬 필요) | 불필요 (BST 구조로 바로 가능) |
| 메모리 활용도 | 낭비 발생 가능 | 노드 단위 관리로 효율적 |
| 랜덤 접근 | 가능 | 불가능 (연결된 노드를 따라가야 함) |
연결 리스트는 임의 접근이 불가능하므로 이진 탐색에 적합하지 않다