본문 바로가기
오늘은 뭘 배울까?/알고리즘

선택 정렬이란?

by Kim Juhwan 2021. 5. 12.

1. 선택 정렬
   1-1. 선택 정렬이란?
   1-2. 움짤로 보는 예시
   1-3. 글로 보는 예시
   1-4. 소스코드
   1-5. 선택 정렬의 시간 복잡도

 

 


 

1. 선택 정렬

1-1. 선택 정렬이란?

정렬 방법 중 가장 느린 것은 버블 정렬.

그리고 그다음으로 느린 방법이 바로 선택 정렬이다.

 

버블 정렬과 마찬가지로 구현이 단순하며 메모리 공간을 추가로 필요로 하지 않는다.

버블 정렬은 자리 바꿈(swap)이 자주 일어나지만 선택 정렬은 평균적으로 그 횟수가 더 적기 때문에

버블 정렬보다 선택 정렬이 항상 더 나은 효율을 보여준다.

 

움짤을 통해 어떻게 하는 정렬 방법인지 알아보도록 하자.

 

1-2. 움짤로 보는 예시

선택 정렬을 하는 과정 (출처: 알고리즘 도감)

 

숫자들 중 가장 작은 값을 선택해서 맨 왼쪽에 있는 값과 교환하는 것이 기본적인 개념이다.

가장 작은 값을 왼쪽에 둠으로써 그 숫자는 정렬이 완료된 것이다. (위 움짤에서는 회색으로 변함)

 

1-3. 글로 보는 예시

 

  • 첫 번째 바퀴

5, 7, 8, 2, 4 중 가장 작은 값을 선택해서 0번째 인덱스의 값과 자리를 바꾼다.

 

짠! 이제 0번째 인덱스는 정렬이 완료되었으므로 검사할 필요가 없다.

 

 

 

  • 두 번째 바퀴

이번엔 7, 8, 5, 4 중에 가장 작은 값을 찾아 1번째 인덱스의 값과 자리를 바꾼다.

7과 4의 자리를 바꾸었다.

 

 

 

  • 세 번째 바퀴

이번엔 8, 5, 7 중에 가장 작은 값을 찾아 2번째 인덱스의 값과 자리를 바꾼다.

8과 5의 자리를 바꾸었다.

 

 

 

  • 네 번째 바퀴

이번엔 8, 7 중에 가장 작은 값을 찾아 3번째 인덱스의 값과 자리를 바꾼다.

8과 7의 자리를 바꾸었다.

 

 

마지막 값은 더 이상 검사할 필요가 없으므로 이것으로 정렬이 완료되었다.

 

 

1-4. 소스 코드

public static void selectionSort(int[] arr) {
    for(int i=0; i<arr.length-1; i++) {
    
    	// 가장 작은 값의 인덱스, 처음에는 맨 앞의 인덱스(i)를 넣어준다.
        int indexMin = i;
        
        // 값을 비교해가며 가장 작은 값의 인덱스를 찾는다.
        for(int j=i+1; j<arr.length; j++) {
            if(arr[j] < arr[indexMin]) {
                indexMin = j;
            }
        }
        
        // 자리 바꿈
        int temp = arr[i];
        arr[i] = arr[indexMin];
        arr[indexMin] = temp;
    }
}

앞서 [목차 1-3]에서 가장 작은 값을 찾는 과정을 생략하고 설명하였는데

실제로는 일일이 값을 2개씩 비교해가며 찾아야 한다.

 

 

1-5. 선택 정렬의 시간 복잡도

주어진 숫자가 총 n개 일때 선택 정렬은 n-1, n-2, ... 1번 비교 연산을 하게 되며 이걸 식으로 바꾸면 n(n-1)/2번이 된다.

즉 O(n²)의 시간 복잡도를 가진다.

 

저번 포스팅에서 가장 느린 정렬 방법인 버블 정렬도 O(n²)의 시간 복잡도를 가진다고 했었는데

시간 복잡도가 비슷하니 둘의 실행 속도는 비슷할까?

[목차 1-1]에서 말했듯이 선택 정렬이 조금 더 효율이 좋으니 조금 빠를까?

이를 알아보기 위하여 난수 데이터 100,000개를 정렬하는데 걸리는 시간을 측정해보았다.

 

 

실행 결과 (선택 정렬인데 오타냄...)

 

세... 세상에... 😲

생각보다 차이가 많이 나서 한 번 놀랐고

버블 정렬이 이렇게 쓰레기였다는 거에 두 번 놀랐다.

 

물론 이 실험 한 번으로 둘의 차이를 단정지을순 없겠지만

확실한 건 버블 정렬보다 선택 정렬이 빠르다는 것이다.

 

 

import java.util.*;

public class Sort {
	public static final int DATASIZE = 100000;
	public static void main(String[] args) {
		int[] arr = makeRandomNumbers();
		int[] copiedArr;
		
		long startTime = System.currentTimeMillis();
		copiedArr = arr.clone();
		bubbleSort(copiedArr);
		long endTime = System.currentTimeMillis();
		System.out.println("버블 정렬: " + (endTime - startTime) / 1000.0 + "초");
		
		startTime = System.currentTimeMillis();
		copiedArr = arr.clone();
		selectionSort(copiedArr);
		endTime = System.currentTimeMillis();
		System.out.println("선택 정렬: " + (endTime - startTime) / 1000.0 + "초");
	}

	public static int[] makeRandomNumbers() {
		Random random = new Random();
		HashSet<Integer> hs = new HashSet<>();
		int[] arr = new int[DATASIZE];
		
		for(int i=0; i<DATASIZE; i++) {
			int number = random.nextInt(DATASIZE);
			
			if(hs.contains(number)) {
				i--;
				continue;
			} else {
				hs.add(number);
				arr[i] = number;
			}
		}
		
		System.out.println("[데이터 개수: " + DATASIZE + "]\n");
		
		return arr;
	}
	
	public static void bubbleSort(int[] arr) {
	    for(int i=0; i<arr.length-1; i++) {
	        for(int j=1; j<arr.length-i; j++) {
	            if(arr[j-1] > arr[j]) {
	                int temp = arr[j-1];
	                arr[j-1]= arr[j];
	                arr[j] = temp;
	            }
	        }
	    }
	}
	
	public static void selectionSort(int[] arr) {
		for(int i=0; i<arr.length-1; i++) {
			int indexMin = i;
			for(int j=i+1; j<arr.length; j++) {
				if(arr[j] < arr[indexMin]) {
					indexMin = j;
				}
			}
			int temp = arr[i];
			arr[i] = arr[indexMin];
			arr[indexMin] = temp;
		}
	}
}

직접 실험을 해보고 싶다면 위의 소스를 실행해보면 된다.

 

 

 


💡 느낀 점

  • 어제에 이어 버블 정렬은 써먹을 게 못된다는 걸 또또 다시 느낌..

📘 참고한 자료


반응형

'오늘은 뭘 배울까? > 알고리즘' 카테고리의 다른 글

퀵 정렬이란?  (2) 2021.05.27
셸 정렬이란?  (0) 2021.05.15
삽입 정렬이란?  (0) 2021.05.13
버블 정렬이란?  (0) 2021.05.11
시간 복잡도란?  (1) 2021.05.10

댓글