Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/Algorithm] 선택 정렬(Selection Sort) 본문

Programming/Algorithm

[Programming/Algorithm] 선택 정렬(Selection Sort)

scii 2021. 3. 8. 01:02

선택 정렬은 버블 정렬보다도 쉽고 간단한 알고리즘이다. 선택 정렬은 정렬순서에 맞게 하나씩 선택해서 옮기는, 옮기면서 정렬이 되게 하는 알고리즘이다.

정렬순서상 가장 앞서는 것을 선택해서 가장 왼쪽으로 이동시키고, 원래 그 자리에 있던 데이터는 빈 자리에 가져다 놓는다.
#include <iostream>

using std::cout;
using std::cin;
using std::endl;

void SelSort(int arr[], int n) {
    int maxIdx;
    int temp;

    for (int i = 0; i < n - 1; i++) {
        maxIdx = i;

        // 최솟값 탐색
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[maxIdx]) {
                maxIdx = j;
            }
        }

        // 교환
        temp = arr[i];
        arr[i] = arr[maxIdx];
        arr[maxIdx] = temp;
    }
}


int main() {
    int arr[4] = { 3, 4, 2, 1 };

    SelSort(arr, sizeof(arr) / sizeof(int));

    for (int i = 0; i < 4; i++) {
        cout << arr[i] << ' ';
    }
    cout << endl;

    return 0;
}


/* 결과

1 2 3 4

*/

선택 정렬(Selection Sort): 성능평가

선택 정렬의 코드만 봐도 버블 정렬과 성능상 큰 차이가 없음을 알 수 있다. 그럼 비교횟수의 확인을 위해 선택 정렬의 일부인 다음 반복문을 보자.

for(int i=0; i<n-1; i++){
  maxIdx = i;
  for(int j=i+1; j<n; j++){
    if(arr[j] < arr[maxIdx]){
      maxIdx = j;
    }
  }
  ...
}

위의 코드에서 바깥쪽 for문의 i가 0일 때 안쪽 for문의 j는 1부터 n-1까지 증가하여 선택 정렬의 비교 연산은 n-1회 진행된다. 그리고 바깥쪽 for문의 i가 1일 때는 안쪽 for문의 j가 2부터 n-1까지 증가하여 선택 정렬의 비교연산은 n-2회 실행된다. 즉 비교연산의 횟수는 다음과 같이 정리가 가능하다.

(n-1) + (n+2) + ... + 2 + 1

그런데 이는 버블 정렬의 경우와 똑같다. 따라서 선택 정렬의 빅-오 역시 최악의 경우와 최선의 경우 구분 없이 다음과 같다.

O(n의 2제곱)

언뜻 생각하기엔 버블 정렬보다 나은 성능을 보장할 것처럼 보였는데, 비교횟수를 기준으로 보면 차이가 없음을 알 수 있다. 그렇다면 데이터의 이동횟수도 버블 정렬과 차이가 없을까? 여기에는 제법 차이가 있다.

버블 정렬이나 선택 정렬이나 데이터의 교환을 위한 세 번의 대입 연산이 다음과 같은 유형으로 진행된다.

temp = A;
A = B;
B = temp;

하지만 존재하는 위치가 다르다. 버블 정렬의 경우에는 안쪽 for문에 속해있다. 반면 선택 정렬의 경우에는 바껕쪽 for문에 속해있다. 때문에 선택 정렬의 경우 n-1회의 교환이 이뤄지므로 데이터의 이동횟수는 이의 세 배인 3(n-1)이 된다. 따라서 선택 정렬의 데이터 이동연산에 대한 빅-오는, 최악의 경우와 최선의 경우 구분 없이 다음과 같다.

O(n)

최악의 경우를 놓고 보면 버블 정렬보다 선택 정렬에 좋은 성능을 기대할 수 있겠지만, 버블 정렬은 최선의 경우에 단 한 번의 데이터 이동도 발생하지 않는다는 점과, 실제로 데이터들이 늘 최악의 상황으로 배치되지는 않는다는 사실을 감안하면, 이 둘의 우열을 가리는 것은 무의미하다고 할 수 있다.

Comments