C++ 개념 공부/알고리즘

[C++] 탐색 - 이진(이분) 탐색(Binary Search)

taene_ 2024. 4. 9. 20:36

<정의>

- 정렬된 리스트(배열)에서 원하는 값(target)의 존재 여부(존재 위치)를 찾는 알고리즘이다.

- 반드시 리스트(배열)를 정렬해서 사용해야 한다는 단점이 있다.

- 탐색할 때마다 검사 범위가 절반으로 줄어든다.

- 재귀함수, 반복문, STL의 3가지 방법을 이용해 이분 탐색(Binary Search)을 실행할 수 있다.

- 시간복잡도 : O(log N)

 

<변수>

1. int left, int right

- 검사 범위의 시작점, 끝점의 인덱스를 가리키기 위한 변수이다.

- left는 시작점을, right는 끝점의 인덱스를 가리킨다.

2. int mid

- 검사 범위 (left ~ right)내에서 실질적으로 검사하는 인덱스를 가리키는 변수이다.

- 검사하는 값은 검사 범위의 중간 값이다.

- 이 값(mid)과 찾고자 하는 값(target)을 비교해서 다음 검사 범위를 변경한다. 

 

<순서>

1. 검사 범위에서 중간 값(mid)을 선택해서 찾고자 하는 값이 같은지 확인한다.

2. 만약 찾고자 하는 값이라면 해당 값을 반환한다.

3. 만약 찾고자 하는 값보다 작다면 (mid < target), 검사 범위를 큰 쪽으로 잡아야 한다.

   그러므로 left = mid + 1을 한다.

4. 만약 찾고자 하는 값보다 크다면 (mid > target), 검사 범위를 작은 쪽으로 잡아야 한다.

   그러므로 right = mid - 1을 한다.

5. 1~4번을 반복하다가 원하는 값이 나오면 해당 값을 반환한다.

6. 위의 과정을 반복하다가 더 이상 검사할 곳이 없으면(left > right)로 탐색을 빠져나온다.

#include <iostream>
using namespace std;

int BinarySearch(int* arr, int size, int answer)
{
	int left = 0;
	int right = size - 1;

	while (left <= right)
	{
		int middle = (left + right) / 2;
		if (answer < arr[middle])
			right = middle - 1;
		else if (answer > arr[middle])
			left = middle + 1;
		else
			return middle;
	}
	return -1;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int arr[] = { 2,4,5,5,6,8,9,10,12,13 };
	int size = sizeof(arr) / sizeof(arr[0]);

	cout << "find number's index:" << BinarySearch(arr, size, 3);

	return 0;
}
//재귀함수
bool binary_search(vector<int>& arr, int start, int end, int target)
{
	if (start > end)
		return false;
	int mid = (start + end) / 2;

	if (arr[mid] == target)
		return true;

	if (arr[mid] > target)
		return binary_search(arr, start, mid - 1, target);

	else
		return binary_search(arr, mid + 1, end, target);
}
//반복문
bool binary_search(vector<int>& arr, int len, int target)
{
    int start = 0, end = len - 1;

    while (start <= end) 
    {
        int mid = (start + end) / 2;

        if (target == arr[mid])
            return true;

        if (target < arr[mid])
            end = mid - 1;

        else if (target > arr[mid])
            start = mid + 1;
    }

    return false;
}
//STL - binary_search()
//binary_search(반복자.시작점, 반복자.끝점, 찾고자 하는 값);
//찾고자 하는 값을 찾으면 true를, 찾지 못하면 false를 반환한다.

vector<int> nums;
int target = 3;
bool isFound = binary_search(nums.begin(), nums.end(), target);
//target(3)이 nums에 있다면 true를, 없다면 false를 반환한다.


// binary_search(nums.begin(), nums.end(), target);
// 첫 번째는 찾고자 하는 범위의 시작점, 두 번째는 찾고자 하는 범위의 끝점이다.(둘 다 반복자(iterator)임)
// 세 번째 매개 변수는 찾고자 하는 수이다. 찾고자 하는 수를 매개 변수로 전달하면 된다.