CS/Data Structure (2021-1)

[자료구조] Binary Search 증명

샤아이인 2022. 1. 22.

 

해당 본문은 학교수업시간에 배운 강의내용을 기반으로 정리하는 요약글 입니다. 정확하지 않은 점이 있으면 지적해주시면 감사하겠습니다.

[자료구조] Binary Search 증명

 

이번 글은 다들 아는 이진탐색에 대한 증명을 배웠다. 사실 이진 탐색 알고리즘 자체는 직관적이고, 이해하기가 쉽다.

문제는 이 당연한 것을 증명하려고 따지다 보니까 머리가 터지는 기분(살아있음에 감사함을)이 들었다.

 

이런거 증명해서 어디다 쓰지? 라고 생각할수도 있지만, 이런건 학생 신분일때 한번은 해봐야 향후 나의 발전에 큰 도움이 될거라 믿어의심치 않는다.

 

Binary Search 의 증명

우선 이진탐색의 코드를 확인해 보자. 아 그리고 이진탐색은 항상 sorting되어있어야만 한다.

int BinarySearch(int a[], int n, int x){
	int left, right, middle;
	left = 0;
	right = n-1;
	
	while(left <= right){
		middle = (left+right)/2;
		if(x == a[middle])
			return middle;
		else if(x < a[middle])
			right = middle-1;
		else
			left = middle+1;
	}
	return -1;
}
 

이를 Invariant를 사용하여 증명해 보자. 아 Invariant가 무엇인지 부터 말하고 시작해야겟다.

Invariant: 단어 의미 그대로 불변하는 조건이다. 이 불변의 조건이 함수가 도는 동안 변화가 없으면 증명되는 것 이다.

 

이진탐색에서는 Invariant를 다음과 같이 정하자.

▶ Invariant: 만약 어떤 index i에 대해서 a[i] = x를 만족하는 i가 있다면, i는 left <= i <= right를 항상 성립한다.

- 알고리즘이 도는 동안 a[i] = x인 i가 없다면, 가정이 거짓으로 귀납적 논리에 의해 left <= i <= right이 성립 하든 말든 Invariant는 참이된다.

- 알고리즘이 도는 동안 a[i] = x인 i가 있다면, left <= i <= right이 항상 성립한다. 이는 Invariant이다.

 

 a[i] = x를 만족하는 i가 없다면 loop는 반드시 끝나고 -1을 반환한다.

 a[i] = x를 만족하는 i가 있다면 loop안에서 반드시 return된다.

	left = 0;
	right = n-1;
 

함수에서 위와 같은 코드가 있다. 즉 left는 배열의 시작 지점을 가리키고, right는 배열의 끝을 가리키고 있는 상황이다. 다음처럼 말이다.

[자료구조] Binary Search 증명 - 				
    
    	Binary Search 의 증명

1) 시작부분

x값이 어디 있든 처음 시작에서는 a[i] = x를 만족하는 i가 있으며, left <= i <= right를 만족하는 i가 존제한다. Invariant는 성립

 

2) while문 안에 들어갔을때

if(x == a[middle])
    return middle;
 

위의 식을 만족한다면, left와 right값은 변하지 않는다. left와 right가 변하지 않았다는 말은 while문에 들어오기 이전의 left와 right값이 그대로 이며, l과 r이 변하지 않은 상태에서 답이 나왔다는것은 a[i] = x를 만족하는 i가 (이전)left <= i <= (이전)right를 만족한다는 말이다. 즉, Invariant는 성립한다.

 

while문 안에는 다음과 같은 코드도 있다.

	else if(x < a[middle])
		right = middle-1;
	else
		left = middle+1;
 

X < a[middle] 를 만족 한다는 말은 => X < a[m+1], a[m+2] ... 을 만족한다는 말이다. 왜냐하면 이들은 sorting되어있기 때문이다. a[m+1], a[m+2] ... 중에는 X = a[i]를 만족하는 i값이 없다. 즉 중간부터 오른쪽 나머지를 버려도 Invariant는 성립한다.

이와 같은 논리로 else 부분의 X > a[middle] 부분도 Invariant는 성립한다.

 

3) -1을 반환하는 경우

-1을 반환하는 경우는 while문의 조건문에서 걸렸다는 말이다.

while(left <= right)
 

코드가 loop를 돌수록 right-left의 값 즉, 배열의 길이는 계속 줄어들게 된다. 결국 (left <= right)조건문이 깨지면 left <= i <= right를 만족하는 i값은 0개가 된다. 이경우도 Invariant는 성립한다.

어떤 i에 대해서 "a[i] = x를 만족하는 i가 있으며, left <= i <= right를 만족하는 i가 존제"가 성립해야 하는데, 이걸 만족하는 i가 없으니 -1을 반환하게 된다.

위에서 말하지 않았는가? 귀납적으로 a[i] = x를 만족하는 i가 없어도 Invariant는 성립한다고 말이다.

 

여기서 없을때 -1을 반환하니, 있을때는 값을 반환한다는 것 을 알 수 있다.

 

4) 증명 완료

함수가 작동하는 동안 Invariant는 계속 성립한다. 따라서 Binary Search는 타당하다.

 

 

 

Recursive Binary Search 의 증명

이번에는 재귀함수 버전의 이진탐색을 증명해보자. 이는 이전보다 훨 간단하다. 우선 코드를 확인해 보자.

int BinarySearch(int a[], int n, int x){
	int left, right, middle;
	left = 0;
	right = n-1;
	middle = (left+right)/2;
	
	if(n == 0) return -1;
        if(x == a[middle])
		return middle;
	else if(x < a[middle])
		return BinarySearch(a, middle, x);
	else{
		int rval;
		rval = BinarySearch(a+middle+1, n-(middle+1), x);
		if(rval == -1) return -1;
		else return rval + m + 1;
	}
}
 

내가 생각한 코드랑 조금 다른데 우선 ppt코드를 사용하겠다.

 

이를 수학적 귀납법으로 증명해 보자.

 

주장: 만약 어떤 i에 대해서 a[i] = x를 만족하는 i가 있다면 i를 return 한다.

 

(1) Base: P(1)이 참인지 확인해야 한다.

n=1인 경우 left는 0, right도 0이다. 1칸짜리 배열이다.

a[i] = x 라면 주장을 만족하는 i가 있으니(여기서는 배열이 한칸이니 index i는 0) 0을 반환할 것 이고, 만족하는 i가 없다면 가정이 틀리게 되니 의논할 여지 없이 그냥 참이다. 귀납적 논리에 의해 말이다.

 

(수업에서는 n=0인 경우를 보여주셧지만, n=1을 보이는 것이 원래 귀납적 증명이라 생각하여 나는 이를 보였다.)

 

(2) Step:

- case 1: a[m] = x를 만족하는 m가 있는경우 m을 반환하니 주장이 성립

- case 2: a[m] > x인 경우 a[m], a[m+1], ... a[n] 중에는 x와 같은 값이 없다. 따라서 a[i] = x를 만족하는 i는 0, 1, ... m-1중 하나이다. 귀납적으로 P(n-1)인 BinarySearch(a, m, x)가 정확하게 index를 return 한다고 가정하면, P(n)도 그 index를 return 하니까 성립

[자료구조] Binary Search 증명 - 				
    
    	Recursive Binary Search 의 증명
위의 그림을 보면 P(n-1)에서 index를 return 하고있다. 이는 P(n-1)을 포함하는 P(n)에서도 index i를 return함을 나타낸다.

- case 3: a[m] < x인 경우 case2와 유사

 

(3) Result: P(n)은 모든 자연수 n에 대해서 참이다.

 

Complexity

T(n) = 1 + T(n2)
          = 1 + 1 + T(n4) = logn
          = O(logn)

logN 시간안에 가능해 진다.

댓글