코디잉

07_정렬 ① 버블정렬/단순선택정렬/단순삽입정렬 본문

자료구조&알고리즘/이론공부

07_정렬 ① 버블정렬/단순선택정렬/단순삽입정렬

yong_ღ'ᴗ'ღ 2022. 8. 26. 23:24
  • 정렬(sorting): key의 대소 관계에 따라 데이터를 일정한 순서로 바꾸는 작업
  • 같은 값을 가진 요소의 순서가 정렬 전/후에도 유지되면 → 『안정된 알고리즘』이라고 한다.
  • 정렬 알고리즘의 핵심 요소: 교환, 선택, 삽입

① 버블 정렬(bubble sort)

- 안정적인 알고리즘 : 이웃한 요소를 비교하고 교환하는 작업을 반복

- O(n²): 효율 좋지 않음

- 모든 정렬이 끝나려면 n - 1회의 패스가 수행되어야 한다.

   1) version 1. 

static void bubbleSort(int[] a) {
    // 방법1. 배열의 뒷쪽부터 비교/교환 수행 → 각 패스에서 가장 작은 값의 요소가 앞으로 옮겨짐
    for (int i = 0; i < a.length-1; i++)
        for (int j = a.length-1; j > i; j--)
            if (a[j-1] > a[j])
                swap(a, j-1, j);

    // 방법2. 배열의 앞쪽부터 비교/교환 수행 → 각 패스에서 가장 큰 값의 요소가 끝으로 옮겨짐
    for (int i = 0; i < a.length-1; i++)
        for (int j = i; j < a.length-1; j++)
            if (a[j] > a[j+1])
                swap(a, j, j+1);
}

 

   2) version 2. 

- 어떤 패스에서 요소의 교환 횟수가 0이면 더 이상 정렬할 요소가 없다는 뜻

- 패스의 교환 횟수를 기록해서, 값이 0이면 계속 실행하지 않고 종료하게끔

static void bubbleSort(int[] a) {
    int exchg;                      
    for (int i = 0; i < a.length-1; i++) {
        exchg = 0;
        for (int j = a.length-1; j > i; j--)
            if (a[j-1] > a[j]) {
                swap(a, j-1, j);
                exchg++;
            }
        if (exchg == 0) break;     // 교환횟수가 0이면 종료
    }
}

 

   3) version 3. 

- 한 번의 패스에서 어떤 시점 이후에 교환이 수행되지 않는다면, 그보다 앞쪽의 요소는 이미 정렬을 마친 상태!

- 마지막으로 교환이 이루어진 오른쪽 요소의 인덱스를 저장해놓고 활용

static void bubbleSort(int[] a) {
   int k = 0;   // a[k]보다 앞쪽은 정렬을 마친 상태
   while (k < a.length - 1) {
       int last = a.length - 1;     // 마지막으로 요소를 교환한 위치
       for (int j = a.length - 1; j > k; j--)
           if (a[j-1] > a[j]) {
               swap(a, j-1, j);
               last = j;
           }
       k = last;
   }

 

   4) 양방향 버블 정렬, 칵테일 정렬, 셰이커 정렬 → 더 적은 횟수로 비교할 수 있음

       : 홀수 번째 패스에는 가장 작은 요소를 맨 앞으로 옮기고, 짝수 번째 패스에는 가장 큰 요소를 맨 뒤로 옮기는 방식

         (패스의 스캔 방향을 교대로 바꿈)

static void shakerSort(int[] a) {
    int front = 0;
    int rear = a.length - 1;  
    int last = a.length - 1;    // swap() 이 끝난 마지막 인덱스 위치
    int count = 1;              // 반복 횟수 세기 위한 변수
    boolean isSwap;             // swap 발생 여부 체크

    // 최대 n-1번 반복하니까
    while (count < a.length) {  
        isSwap = false;
        // 홀수: 가장 작은 요소를 맨 앞으로 옮김(뒤부터 스캔)
        if (count % 2 == 1) {
            for (int j = rear; j > front; j--)
                if (a[j-1] > a[j]) {
                    swap(a, j-1, j);
                    isSwap = true;
                    last = j;
                }
            front = last;
        }
        // 짝수: 가장 큰 요소를 맨 뒤로 옮김(앞부터 스캔)
        else {
            for (int j = front; j < rear; j++)
                if (a[j] > a[j+1]) {
                    swap(a, j, j+1);
                    isSwap = true;
                    last = j;
                }
            rear = last;
        }

        if (front == a.length - 1 || front == rear || isSwap == true) break;
    }
}

 

② 단순 선택 정렬

- 불안정적인 알고리즘: 서로 떨어져 있는 요소를 교환(같은 값을 가진 요소의 순서가 뒤바뀔 수 있음)

- O(n²): 효율 좋지 않음

: 가장 작은 요소부터 선택해 알맞은 위치로 옮겨서 순서대로 정렬하는 알고리즘

<교환 과정>

1. 아직 정렬하지 않은 부분에서 가장 작은 값을 찾음

2. 가장 작은 값과 아직 정렬하지 않은 부분의 첫 번째 요소를 교환

→ 이 과정을 n - 1회 반복하면 된다.

static void selectionSorting(int[] a) {
    for (int i = 0; i < a.length - 1; i++) {
        int min = i;        // 아직 정렬되지 않은 부분에서 가장 작은 요소의 인덱스 값 저장
        for (int j = i + 1; j < a.length; j++)
            if (a[min] > a[j])
                min = j;
        swap(a, i, min);    // 아직 정렬되지 않은 부분의 첫 요소와 가장 작은 요소를 교환
    }
}

 

③ 단순 삽입 정렬(셔틀 정렬, shuttle sort)

- 안정적인 알고리즘: 떨어져 있는 요소들이 서로 뒤바뀌지 않음

- O(n²): 효율 좋지 않음

- 선택한 요소를 그보다 더 앞쪽의 알맞은 위치에 삽입하는 작업을 반복하여 정렬하는 알고리즘

- 2번째 요소부터 선택하여 진행,

  아직 정렬되지 않은 부분의 첫 번째 요소를 정렬된 부분의 알맞은 위치에 삽입

  → 이 과정을 n - 1회 반복하면 된다.

static void insertionSort(int[] a) {
    for (int i = 1; i < a.length; i++) {
        int j;
        int temp = a[i];
        for (j = i; j > 0 && a[j - 1] > temp; j--)
            a[j] = a[j - 1];
        a[j] = temp;
    }
}

 

'자료구조&알고리즘 > 이론공부' 카테고리의 다른 글

09_문자열 검색  (0) 2022.09.13
08_집합  (0) 2022.09.13
06_재귀 알고리즘  (0) 2022.08.26
05_큐(queue)  (0) 2022.08.19
04_스택(stack)  (0) 2022.08.19
Comments