2016. 12. 9. 14:01

안녕하세요. 게임개발자 놀이터 입니다.


이번 포스팅에선 퀵 정렬에 대해 정리해보려고 해요.



퀵정렬 (Quick Sort)


퀵정렬은 '찰스 앤터니 리처드 호어(1962)'가 개발한 정렬 알고리즘 이라고 합니다.


퀵 정렬은 기준(pivot)을 선택하여 기준보다 작은 데이터를 왼쪽에 위치시키고, 큰 데이터는 오른쪽에 위치시킵니다.

이 과정이 끝나면 기준(pivot)이 된 요소는 정렬된 위치를 찾습니다. 결과적으로 기준보다 작은 데이터는 왼쪽, 큰 데이터는 오른쪽에 위치하게됩니다. 이러한 알고리즘을 pivot을 기준으로 왼쪽 데이터 그룹과 오른쪽 데이터 그룹에 재귀적으로 더이상 불가능 할때까지 반복합니다. (데이터 그룹의 갯수가 0 이거나 1개일때까지 반복)

반복이 종료되면 정렬된 데이터 그룹을 얻을 수 있습니다.


(출처 : 위키백과 퀵정렬)


렬과정



임의의 데이터 배열을 가지고 정렬 해보겠습니다.

15 13 9 10 26 24 85


1. 먼저 Pivot을 설정합니다.

15 13 9 10 26 24 85


2. Pivot(15)를 기준으로 보다 작으면 왼쪽, 크면 오른쪽에 위치시켜 분할합니다

13 9 03 15 26 24 85


3. 좌 우 로 분할된 데이터로 다시 (1,2)의 과정을 실행합니다.


( 13 9 10 )   15   ( 26 24 85 )

( 13 9 10 )   15   ( 26 24 85 )

( 9 10 13 )   15   ( 26 24 85 )

9 10 )   13 15   ( 26 24 85 )


9 10 13 15   ( 26 24 85 )

9 10 13 15   ( 26 24 85 )
9 10 13 15   ( 24 26 85 )


9 10 13 15 24 26 85


정렬 완성!


예제 코드


2개의 함수와 재귀함수를 이용한 방법

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
31
32
33
34
35
36
37
38
39
40
41
void QuickSort(int arrays[], int left, int right)
{
    if(left<right)
    {
        int pivot = Partition(arrays,left,right);
        QuickSort(arrays, left, pivot-1);
        QuickSort(arrays, pivot+1, right);
    }
}
 
int Partition(int arrays[],int left, int right)
{
    int pivot = left;
    right = right +1;
 
    while(left<right)
    {
        do
        {
            ++left;
        }while(arrays[left] < arrays[pivot]);
 
        do
        {
            --right;
        }while(arrays[right] > arrays[pivot]);
 
        if(left<right)
        {
            int swap = arrays[left];
            arrays[left] = arrays[right];
            arrays[right] = swap;
        }
    }
 
    int swap = arrays[pivot];
    arrays[pivot] = arrays[right];
    arrays[right] = swap;
 
    return right;
}
cs


1개의 재귀 함수를 이용한 방법


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
void QuickSort(int arrays[], int left, int right)
{
    int row = left;
    int high = right;
    int pivot = arrays[(left + right) / 2];
 
    while (row <= high) {
        while (arrays[row] < pivot)
            row++;
        while (arrays[high] > pivot)
            high--;
 
        if (row <= high) {
            int tmp = arrays[row];
            arrays[row] = arrays[high];
            arrays[high] = tmp;
            row++;
            high--;
        }
    };
 
    if (left < high)
        QuickSort(arrays, left, high);
 
    if (row < right)
        QuickSort(arrays, row, right);
}
cs




알고리즘 분석



가장 평균의 상황에서의 시간복잡도가 알고리즘의 시간 복잡도라고 할 수 있다.


크게 2가지 상황을 추축할수있다.


1. 최고의 경우, 나누어지는 족족 마다 반씩 분할되는 경우.

2. 최악의 경우, 나누어지는 족족마다 1개와 나머지로 분할되는 경우.


우선 1번의 경우를 계산하면. 


횟수 = (2ⁿ - 1) + 2 x (2ⁿ-¹ - 1) ...

= ⁿ-¹Σ 2... 이거 수식을 어떻게 적어야 할지 모르겠다..


계산하면.. NLogN이 나온다.


2번의 경우는 N² 이 나온다.


나중에 수식을 제대로 추가할수있는 방법을 알게된다면.. 그때 수정 해야겠다.



쨋든 2번의 경우는 극단적인 상황이므로, 시간 복잡도는 1번의 경우를 사용해서 O(N logN) 이다.


감사합니다.



동영상 예시

출처 : 유투브동영상







Posted by 시리시안
2016. 12. 8. 17:10


안녕하세요. 게임 개발자 놀이터입니다.


이번 포스팅에선 선택 정렬에 대해서 정리해보려고해요.


벌써 버블, 삽입 2개를 하고 선택정렬할 차례네요..


간단한건 이제 끝나가는군요.



선택 정렬


선택 정렬은 크게 3가지 방법으로 정렬을 합니다.


1. 주어진 배열에서 최솟값을 찾는다.

2. 그 값을 배열 맨앞에 위치한 값과 교체한다.

3. 맨 처음 위치를 뺀 나머지 배열을 같은 방법으로 교체한다.



정렬 과정


우선 랜덤하게 숫자를 배열해보겠습니다.


9 5 4 3 8 1 7


우선 정렬이 안된 배열 {9 5 4 3 8 1 7} 에서 최 하위 값을 찾습니다.


1 이군요. 찾은 값을 젤 처음 값과 교체합니다.


9 5 4 3 8 1 7 => 1 5 4 3 8 9 7


이렇게 한번의 루프가 끝났습니다.


두번째는 맨 처음 값 그러니까 교체가 된 1을 제외한 배열을 정렬합니다.


1 { 5 4 3 8 9 7 } 에서 최 하위 값을 찾습니다. 3 이군요. 1을 제외한 배열 처음과 교체합니다.


1 3 4 5 8 9 7 이 되겠군요.


이런식으로 마지막까지 진행하면 정렬이 됩니다.


밑의 그림을 참고해주세요.


(출처 : 위키백과 선택정렬)



예제 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void SelectionSort(int arrays[], int length) 
{
    for(int i=0; i<length; ++i)
    {
        int Minindex = i;
        for(int j= i+1; j<length; ++j)
        {
            if(arrays[j] < arrays[Minindex])
                Minindex = j;
        }
 
        int swap = arrays[i];
        arrays[i] = arrays[Minindex];
        arrays[Minindex] = swap;
    }
}
cs


간단하게 구현했습니다.



알고리즘 분석


선택 정렬은 최소값을 구하기 위해 전부 비교를 해야합니다. 따라서


(n-1) + (n-2) + ..... + 2 + 1 = n(n-1)/2 가 됩니다.


빅 오 표기법으로 시간 복잡도는 O(N²)가 되겠습니다.




그림 예시 자료



(출처:  위키백과 선택정렬 )


동영상 예시 자료

( 출처 : Youyube )




감사합니다.

Posted by 시리시안
2016. 12. 8. 15:41

안녕하세요. 게임개발자 놀이터 입니다.


이번 포스팅에선 삽입 정렬에 대하여 정리 해보려합니다.



삽입 정렬 ( Insertion Sort )


삽입 정렬은 자료 배열의 모든 요소를 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여 자신의 위치를 찾아 삽입해서 정렬하는 알고리즘 입니다.

삽입 정렬의 경우 첫번째 요소를 이미 정렬됬다. 라고 간주 한 후 정렬을 시작합니다.

정렬되지않은 요소는 목록의 제일 뒤에있는 요소 부터 정렬된 목록과 비교하여 적절한 위치에 삽입합니다.

이 작업을 끝까지 반복하면 모든 요소가 정렬됩니다.


말로만 설명하면 좀 어려울수 있습니다.


정렬 과정


간단하게 삽입 정렬 예시를 보여드리겠습니다.


아래와 같이 5개의 숫자가 주어졌다고 했을때, 삽입 정렬로 정렬 해보겠습니다.


4 9 2 5 7


삽입정렬은 첫번째 요소는 정렬이 되었다고 판단하고, 두번째 부터 시작합니다.


첫번째

4 / □ 2 5 7  | key 값 = 9

9는 4보다 크니까 4보다 뒤쪽에 위치한다. □ 2 5 7 

4 / 9 2 5 7 


두번째

4 9 / □ 5 7 | key 값 = 2

2는 9보다 작으니까 9보다 앞 쪽에 위치한다. □ 9 5 7 

2는 4보다 작으니까 4보다 앞 쪽에 위치한다. □ 4 9 5 7

2 4 / 9 5 7


세번째

2 4 9 / □ 7 | key 값 = 5

5는 9보다 작으니까 9보다 앞쪽에 위치한다. 2 4  9 7

5는 4보다 크니까 4보다 뒤쪽에 위치한다. 2 4  9 7

2 4 5 / 9 7


네번째

2 4 5 9 / □ | key 값 = 7

7은 9보다 작으니까 9보다 앞쪽에 위치한다. 2 4 5 □ 9

7은 5보다 크니까 5보다 뒤쪽에 위치한다. 2 4 5 □ 9

2 4 5 7 9


정렬이 완료 되었습니다.


이처럼 첫번째 값을 제외하고 key 값으로 돌아가며 정렬이 완료된 부분과 비교하며 삽입을 하면 됩니다.

(사진 출처 : 나무위키 삽입정렬)



예제 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void InsertionSort(int arrays[], int length)
{
    int key = -1;
 
    for(int i=1; i<length; ++i)
    {
        key = arrays[i]; // 두번째 값부터.
        int j=i-1;
        for(; j>=0--j)
        {
            if(arrays[j] > key)
            {
                arrays[j+1= arrays[j];
            }
            else
            {
                break;
            }
        }
        arrays[j+1= key;
 
    }
}
cs


간단하게 구현했습니다.



알고리즘 분석


비교 횟수

삽입정렬은 두번째 요소부터 첫 요소와 비교하여 정렬한후 세번째 요소는 두번째와 첫번째와 비교합니다.

물론 이미 정렬되어있다면 비교를 하지 않겠지만, 빅오 표기법으로 생각하여 최악의 경우는 전부 비교하는겁니다.

0 + 1 + 2 + 3 .... + n-2 + n-1 = n(n-1)/2 가 되겠군요.


따라서 최악의 경우 시간 복잡도는 O(N²) 가 되겠습니다.


최선의 경우는 비교는 O(1)이고 for문이 Length-1 만큼 돌아야하니 O(n)이겠군요.





밑의 자료는 제가 삽입정렬에 대한 자료를 찾다가 발견한 자료들입니다.


삽입 정렬의 이미지 예시 

( 출처 : 위키 백과 : 삽입 정렬 )



삽입 정렬의 동영상 예시

출처 ( 유투브 동영상(클릭) )



감사합니다.

Posted by 시리시안
2016. 12. 8. 13:56

안녕하세요. 게임 개발자 놀이터입니다.


이번 포스팅에선 버블 정렬에 대하여 설명해보려고 합니다.




버블 정렬 ( Bubble Sort )


버블 정렬 ( Bubble Sort )은 인접한 두 수 를 비교하여 큰 수를 뒤로 보내는 간단한 정렬 알고리즘입니다.

시간 복잡도는 O(N²)을 가지고 있습니다. 속도는 느린 편 이지만, 코드가 단순 해서 자주 언급됩니다.


원소의 이동이 꼭 거품이 수면으로 올라오는듯한 모습을 보이기 때문에 Bubble sort 라는 이름을 가지게 되었다고 합니다.



정렬 과정


간단하게 버블 정렬의 예시를 보여드리겠습니다.


아래와 같이 5개의 숫자가 주어졌다고 했을때,  Bubble Sort로 정렬 해보겠습니다.


9 5 1 3 7


먼저 첫번째 인덱스와 두번째 인덱스를 비교합니다.


9와 5, 9가 더 크므로 두 수 의 자리를 바꿉니다.


교제 전 : 9 5 1 3 7


교체 후 : 5 9 1 3 7


다음 인덱스를 하나 늘려서 두번째 인덱스와 세번째 인덱스를 비교합니다.


9와 1, 9가 더 크므로 두 수의 자리를 바꿉니다.


교체 전 : 5 9 1 3 7


교체 후 : 5 1 9 3 7


계속해서 인덱스를 늘려가며 값을 비교하고 자리를 바꿔줍니다.


교체 전 : 5 1 9 3 7

교체 후 : 5 1 3 9 7


교체 전 : 5 1 9 7

교체 후 : 5 1 3 7 9


이렇게 한번의 순회가 끝났습니다. 한바퀴의 순회가 끝나니까 가장 큰 수인 9는 자리 자리를 찾아갔습니다.


그럼 다음 순회에선 맨 마지막 원소는 방문할 필요가 없어졌네요.


맨 마지막 원소인 9는 고정하고 나머지 원소도 진행 해봅시다.


교체 전 : 5 1 3 8 9

교체 후 : 1 5 3 7 9


교체 전 : 1 5 3 7 9

교체 후 : 1 3 5 7 9


교체 전 : 1 3 5 7 9

교체 후 : 1 3 5 7 9


두번째 순회가 끝났네요. 예시로 랜덤하게 적은 숫자가 2번의 순회 만으로 정렬이 완료되어버렸네요.


그래도 어느정도 느낌을 잡힐꺼라 생각합니다.


이런게 바로 버블 정렬입니다! 하하


원소들이 큰 순서대로 뒤로 밀려가서 거품처럼 정렬되는 모습이었습니다.



예제 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void BubbleSort(int arrays[], int length)
{
    for(int i=0; i<length; ++i)
    {
        forint j=0; j < length-i-1 ; ++j)
        {
            if(arrays[j] > arrays[j+1])
            {
                int swap = arrays[j];
                arrays[j] = arrays[j+1];
                arrays[j+1= swap;
            }
        }
    }
}
cs


간단하게 구현했습니다.



알고리즘 분석


정렬 알고리즘은 분석을 할 필요가 있습니다.


제가 위에 시간 복잡도가 O(N²)라고 적어두긴 했지만 어떻게 구하는지도 알아야 합니다.


비교 횟수


버블 정렬은 한번의 순회를 마칠때마다 비교 대상이 하나씩 줄어듭니다.

전체 원소 갯수를 n개 라고 하면 총 n-1번의 순회를 돌면 정렬이 끝나게 됩니다.

5개의 원소 배열을 정렬한다면 4+3+2+1 = 10번 비교 하게 됩니다.

이를 수식화 하게되면


(n-1) + (n-2) + (n-3) + ... + 3 + 2 + 1 = ( n-1 ) * n / 2 = n(n-1)/2


이렇게 됩니다.


자리 교환 횟수


최선의 경우, 그러니까 이미 정렬된 원소 배열일 경우, 정렬 과정중 자리 교환이 한번도 일어나지 않을겁니다.

최악의 경우, 원소들을 비교할때마다 자리교환이 일어나므로, 자리교환 횟수 또한 비교횟수와 같아질 것입니다.


최선의 경우 교환 횟수 : 0

최악의 경우 교환 횟수 : n(n-1)/2


비교 횟수 와 자리 교환 횟수를 더하면 n²-n 이 되는데 시간 복잡도는 상수는 생략하고 최고차항만 생각합니다.


따라서 시간 복잡도는 빅 오 표기법으로 O(N²) 이 됩니다.





밑의 자료는 제가 버블정렬에 대한 자료를 찾다가 발견한 자료들입니다.

버블 정렬의 이미지 예시 




버블 정렬의 동영상 예시

출처 ( 유투브 동영상(클릭) )





감사합니다.

Posted by 시리시안