본문 바로가기

Java/자료구조

3-3 이진 검색

1. 이진 검색

 

이진 검색(binary search)

- 요소가 오름차순 또는 내림차순으로 정렬된 배열에서 검색하는 알고리즘 

 

- pl = 검색 범위의 맨 앞 인덱스 , 0

- pr = 검색 범위의 맨 끝 인덱스 , n-1

- pc = 검색 범위의 중앙 인덱스 , (n-1)/2

 

- 이진 검색을 한 단계씩 진행할 때마다 검색범위가 반으로 좁혀짐

 

 

 

1) a[pc] < key 일 때

 

- a[pl] ~ a[pc]는 key보다 작은 것이 분명하므로 검색대상에서 제외

- 검색 범위를 중앙 요소 a[pc]보다 뒤쪽인 a[pc+1] ~ a[pr]로 좁힘 

- pl값을 pc+1로 업데이트 

 

2) a[pc] >key일 때

 

- a[pc] ~ a[pr]은 key보다 큰 것이 분명하므로 검색 대상에서 제외

- 검색 범위를 중앙 요소 a[pc]보다 앞쪽인 a[pl] ~ a[pc-1]로 좁힘 

- pr 값을 pc-1로 업데이트 

 

 

3) 이진 검색 알고리즘의 종료 조건 

 

1. a[pc]와 key가 일치

2. 검색 범위가 더 이상 없음 (pr<pl이 되면 검색 종료!)

 

//이진 검색 
import java.util.Scanner;

public class BinSearch {
	//요솟수가 n개인 배열 a에서 key와 같은 요소를 이진 검색 
	static int binSearch(int[] a, int n, int key)
	{
		int pl = 0; //검색 범위의 첫 인덱스 
		int pr = n-1; //검색 범위의 끝 인덱스 
		
		do {
			int pc = (pl+pr)/2; //중앙 요소의 인덱스 
			if(a[pc] ==key)
				return pc; //검색 성공
			else if(a[pc]<key)
				pl=pc+1; //검색 범위를 뒤쪽 절반으로 좁힘
			else
				pr=pc-1; //검색 범위를 앞쪽 절반으로 좁힘
		}while(pl<=pr);
		
		return -1; //검색 실패 
	}
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.print("요솟수: ");
		
		int num = sc.nextInt();
		int[] x = new int[num]; //요솟수가 num인 배열 
		
		System.out.println("오름차순으로 입력하세요.");
		
		System.out.println("x[0]: "); //첫 요소를 입력 받음 
		x[0] = sc.nextInt();
		
		for(int i=1; i<num; i++) {
			do {
				System.out.print("x["+i+"]: ");
				x[i] = sc.nextInt();
			}while(x[i]<x[i-1]); //바로 앞의 요소보다 작으면 다시 입력받음 
		}
		
		System.out.print("검색할 값: ");
		int key = sc.nextInt();
		
		int index = binSearch(x,num,key); //배열 x에서 값이 key인 요소를 검색 
		
		if(index ==-1)
			System.out.println("그 값의 요소가 없습니다.");
		else
			System.out.println("그 값은 x["+index+"]에 있습니다.");
		
		
		
	}

}

 

 

 

2. 복잡도 

 

복잡도(complexity)

- 알고리즘의 성능을 객관적으로 평가하는 기준 

 

- 시간 복잡도(time complexity) 

  -> 실행에 필요한 시간을 평가한 것 

 

- 공간 복잡도(space complexity)

  -> 기억 영역과 파일 공간이 얼마나 필요한가를 평가한 것 

 

 

1) 선형 검색의 시간 복잡도 

 

static int seqSearch(int[] a, int n, int key)
{
    int i=0; //1)
    
    while(i<n){ //2)
    	if(a[i] == key) //3)
        	return i; //4)
         i++; //5)
    }
    
    return -1; //6)
}

 

- 각 단계별 실행 횟수 

단계 실행 횟수 복잡도
1 1 O(1)
2 n/2 O(n)
3 n/2  O(n)
4 1 O(1)
5 n/2 O(n)
6 1 O(1)

 

- 한 번만 실행하는 복잡도는 O(1)

- 배열의 맨 끝에 도달했는지를 판단하는지(2)와 현재 선택한 요소와 찾고자 하는 값이 같은지를 판단하는 (3)의 평균 실행 횟수는 n/2 

 -> n에 비례하는 횟수만큼 실행하는 복잡도는 O(n)

 

- 2개 이상의 복잡도로 구성된 알고리즘의 전체 복잡도는 차수가 더 높은 쪽의 복잡도가 지배

O(1)+O(n)+O(n)+O(1)+O(n)+O(1) = O(max(1,n,n,1,n,1)) = O(n)

 

 

2) 이진 검색의 시간 복잡도 

 

static int binSearch(int[] a, int n, int key)
	{
		int pl = 0; //검색 범위의 첫 인덱스 1)
		int pr = n-1; //검색 범위의 끝 인덱스 2)
		
		do {
			int pc = (pl+pr)/2; //중앙 요소의 인덱스 3)
			if(a[pc] ==key) //4)
				return pc; //검색 성공 5)
			else if(a[pc]<key) //6)
				pl=pc+1; //검색 범위를 뒤쪽 절반으로 좁힘 7)
			else
				pr=pc-1; //검색 범위를 앞쪽 절반으로 좁힘 //8)
		}while(pl<=pr); //9)
		
		return -1; //검색 실패 //10)
	}

 

- 각 단계별 실행 횟수 

단계 실행 횟수 복잡도
1 1 O(1)
2 1 O(1)
log n  O(log n)
4 log n  O(log n)
5 1 O(1)
6 log n  O(log n)
7 log n O(log n)
8 log n  O(log n)
log n  O(log n)
10 1 O(1)

 

이진 검색 복잡도 

O(1)+O(1)+O(log n)+O(log n)+...+O(1) = O(log n)

 

 

3. Arrays.binarySearch에 의한 이진 검색 

 

- 배열에서 이진 검색을 하는 메서드 

- 오름차순으로 정렬된 배열 a를 가정하고 값이 key인 요소를 이진 검색 

- 자료형과 관계없이 검색할 수 있도록 자료형에 따라 9가지 방법으로 오버로딩됨 

 

1) 검색에 성공한 경우 

 

- key와 일치하는 요소의 인덱스를 반환 

 

2) 검색에 실패한 경우 

 

- 배열 안에 key가 있어야 할 위치(삽입 포인트)를 추정할 수 있는 값을 반환 

- 삽입 포인트를 x라고 할 때 반환 값은 -x-1

- 검색하기 위해 지정한 key보다 큰 요소 중 첫 번째 요소의 인덱스 

 

ex) 31을 검색 

 

- 31을 검색하면 31은 인덱스(4)와 인덱스(5) 사이에 위치해야 하므로 삽입 포인트는 5

- -6을 반환 

 

 

ex) 95를 검색 

- 95를 검색하면 모든 요소가 검색하는 값보다 작기 때문에 삽입 포인트는 배열의 길이인 10이 됨 

- -11을반환 

 

 

import java.util.Arrays;
import java.util.Scanner;

public class BinarySearchTester {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		System.out.print("요솟수: ");
		int num = sc.nextInt();
		int[] x = new int[num]; //요솟수가 num인 배열 
		
		System.out.println("오름차순으로 입력하세요.");
		
		System.out.print("x[0]: ");
		x[0] = sc.nextInt();
		
		for(int i=1; i<num; i++) {
			do {
				System.out.print("x["+i+"]: ");
				x[i] = sc.nextInt();
			}while(x[i]<x[i-1]); //바로 앞의 요소보다 작으면 다시 입력받음 
		}
		
		System.out.print("검색할 값: ");
		int key = sc.nextInt();
		
		int index = Arrays.binarySearch(x, key); //배열 x에서 값이 key인 요소를 검색
		
		if(index < 0)
			System.out.println("그 값의 요소가 없습니다.");
		else
			System.out.println("그 값은 x["+index+"]에 있습니다.");
	}
	
	 
}

'Java > 자료구조' 카테고리의 다른 글

3-2 선형 검색  (1) 2024.02.01
3-1 검색 알고리즘  (0) 2024.01.31
2-2 클래스  (0) 2024.01.28
2-1 배열  (0) 2024.01.28
1-2. 반복  (1) 2024.01.27