Keep going

정렬 -1 본문

Records/자료구조&알고리즘

정렬 -1

코딩천재홍 2021. 1. 29. 16:37

정렬이란?

정렬은 이름, 학번, 키 등 핵심 항목의 대소 관계에 따라 데이터 집합을 일정한 순서로 줄지어 늘어서도록 바꾸는 작업을 말한다.

 

안정된 정렬이란?

같은 값의 키를 가진 요소의 순서가 정렬 전후에도 유지되는 것을 말한다.

 

내부 정렬 : 정렬할 모든 데이터를 하나의 배열에 저장할 수 있는 경우에 사용하는 알고리즘

외부 정렬 : 정렬할 데이터가 너무 많아서 하나의 배열에 저장할 수 없는 경우에 사용하는 알고리즘

 

1. 버블 정렬

버블 정렬은 이웃한 두 요소의 대소 관계를 비교하여 교환을 반복한다.

static void bubbleSort(int[] a, int n) {
        for (int i = 0; i < n - 1; i++) {
            int exchg = 0;
            for (int j = n - 1; j > i; j--) {
                if (a[j - 1> a[j]) {
                    swap(a, j - 1, j);
                    exchg++;
                }
            }
            if (exchg == 0)
                break;
        }
    }
cs

어떤 패스에서 교환 횟수가 0이면 더 이상 정렬할 요소가 없다는 뜻이기 때문에 정렬을 멈추면 된다.      exchg = 한 번의 패스에서 시도한 교환 횟수 (0이면 정렬을 마친 것)

 

static void bubbleSort2(int[] a, int n) {
        int k = 0;
        while (k < n - 1) {
            int last = n - 1;
            for (int j = n - 1; j > k; j--) {
                if (a[j - 1> a[j]) {
                    swap(a, j - 1, j);
                    last = j;
                }
            }
            k = last;
        }
    }
cs

각각의 패스에서 비교, 교환을 하다가 어떤 시점 이후에 교환이 수행되지 않는다면 그보다 앞쪽의 요소는 이미 정렬을 마친 상태라고 생각해도 좋다.

last = 각 패스에서 마지막으로 교환한 두 요소 가운데 오른쪽 요소의 인덱스 값

k = 수행할 패스의 범위를 제한하는 용도

 

2. 선택정렬

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

static void selectionSort(int[] a, int n) {
        for (int i = 0; i < n - 1; i++) {
            int min = i;
            for (int j = i + 1; j < n; j++) {
                if (a[j] < a[min])
                    min = j;
            }
            swap(a, i, min);
        }
    }
cs

선택 정렬 알고리즘은 서로 떨어져 있는 요소를 교환하는 것이기 때문에 안정적이지 않습니다.

 

 

3. 삽입정렬

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

static void insertionSort(int[] a, int n) {
        for (int i = 1; i < n; i++) {
            int j;
            int tmp = a[i];
            for (j = i; j > 0 && a[j - 1> tmp; j--) {
                a[j] = a[j - 1];
            }
            a[j] = tmp;
        }
    }
cs

삽입 정렬 알고리즘은 떨어져 있는 요소들이 서로 뒤바끼지 않아 안정적이다. 

 

버블 정렬, 선택 정렬, 삽입 정렬의 시간 복잡도 → O(n2)이다.

 

4. 셸 정렬

셸 정렬은 단순 삽입 정렬의 장점은 살리고 단점은 보완하여 좀 더 빠르게 정렬하는 알고리즘이다.

 

-단순 삽입 정렬의 특징

장점 : 정렬을 마쳤거나 정렬을 마친 상태에 가까우면 정렬 속도가 매우 빨라진다.

단점 : 삽입할 위치가 멀리 떨어져 있으면 이동 해야 하는 횟수가 많아진다.

 

셸 정렬은 먼저 정렬할 배열의 요소를 그룹으로 나눠 각 그룹 별로 단순 삽입 정렬을 수행하고, 그 그룹을 합치면서 정렬을 반복하여 요소의 이동 횟수를 줄이는 방법

여러개의 그룹으로 나누어 정렬하는 이유 : 정렬이 된 상태에 가까운 배열로 만들어 놓기 위해서.

static void shellSort(int[] a, int n) {
        for (int h = n/2; h >0 ; h/=2) { // 증분값 3, 1....
            for (int i = h; i < n ; i++) {
                int j;
                int tmp =a[i];
                for (j = i -h; j>= 0 && a[j] > tmp; j-=h) {
                    a[j +h] = a[j];
                }
                a[j+h] = tmp;
            }
        }
    }
cs

그룹을 나누고 합칠 때 섞이지 않으면 다시 처음 단계와 다를게 없다.

이런 문제를 해결하기 위해서는 h값이 서로 배수가 되지 않도록 해야 한다.

static void shellSort2(int[] a, int n) {
        int h;
        for (h=1; h<n/9; h=h*3+1);
 
        for ( ; h >0 ; h/=3) {
            for(int i =h; i<n; i++) {
                int j;
                int tmp = a[i];
                for (j=i-h; j>=0 && a[j] > tmp; j-=h) {
                    a[j+h] = a[j];
                }
                a[j+h] = tmp;
            }
        }
    }
cs

h의 초깃값은 너무 크면 효과가 없기 때문에, 배열의 요솟수 n을 9로 나눈 값을 넘지 않도록 정한다.

 

셸 정렬의 시간 복잡도는 O(n1.25) 으로 기존의 단순 정렬보다는 빠르지만, 

이 알고리즘도 멀리 떨어져 있는 요소를 교환해야 하므로 안정적이지 않다.

 


출처 : Do it! 자료구조와 함께 배우는 알고리즘 입문 : 자바 편 [시바타 보요, 옮긴이 : 강민 (이지스퍼블리싱)]

'Records > 자료구조&알고리즘' 카테고리의 다른 글

정렬 -3  (0) 2021.01.30
정렬 -2  (0) 2021.01.30
재귀 알고리즘  (0) 2021.01.27
  (0) 2021.01.23
스택  (0) 2021.01.04
Comments