알고리즘

[알고리즘][정렬] 퀵 정렬

몽실이 2021. 2. 23. 21:20

퀵 정렬이란

 

"병합 정렬" 과 같이 가장 많이 사용되고 빠른 정렬 알고리즘  

기준 데이터(Pivot)을 설정하고 그 기준보다 큰 데이터작은 데이터의 위치를 바꾸는 방법

시간 복잡도는 평균 O(NlogN) 이지만 이미 정렬이 되어잇는 경우 최대 O(N2) 까지 늘어날 수 있다.

정렬 방법

기준 데이터(pivot)를 설정하고 그 기준보다 큰 데이터 작은 데이터위치를 바꾸는 형식

호어 분할방식을 기준으로 리스트에 첫 번쨰 데이터 pivot으로 설정

 

[Step 1]

왼쪽으로 부터기준 데이터보다 큰 데이터를 찾고 

오른쪽으로 부터기준 데이터보작은 데이터를 찾는다

 

[Step 2]

두 데이터 값 인덱스가 교차하지 않는다면

값을 교환 후 다시 반복한다.

 

[Step 3]

만약 두 데이터의 인덱스 값이 교차 된다면

오른쪽으로부터의 RightIndex의 값기준 데이터(pivot)교체 후 

RightIndex에 할당되어 있는 값기준 데이터(pivot)로 잡고 양쪽으로 분할한다.

 

[Step 4]

그후 왼쪽에는 RightIndex - 1 값을 끝으로 

오른쪽에는 RightIndex +1 값을 시작으로  

설정하여 재귀를 반복하여 정렬한다.


예시 자료

 

 

 

설명 : 5를 기준 데이터(pivot)으로 잡고 왼쪽으로부터 기준 데이터보다 큰값 7

오른쪽으로 부터 기준데이터보다 작은 값 4를 발견했으나 두 값의 Index가 교차하지 않으므로 두 값만 교체한다.

 

 

 

 

 

설명 : 위와 같이 5를 기준 데이터(pivot)으로 잡고 왼쪽으로부터 기준 데이터보다 큰 값 9

오른쪽으로 부터 기준 데이터보다 작은 값 2를 발견했으나 두 값의 Index가 교차하지 않으므로 두 값만 교체한다.

 

 

 

설명 : 하지만 왼쪽으로 부터 기준 데이터보다 큰 값 6

오른쪽으로 부터 기준 데이터보다 작은 값 1를 발견했으나 두 값의 Index가 교차하므로 RightIndex의 값 1

기준 데이터 5교체한후 양쪽으로 분할한다. 

 

 

 

 

 

 

 

 

 

설명 : 그 후 위와 같은 식으로양옆으로 각각 다시 반복하는 재귀함수를 통해 정렬한다.

 


■ 직접 작성한 코드(c#)

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
public static class MyCode
{
    public static void MyQuickSort(int[] _arr, int _startIndex, int _endIndex)
    {
        if (_startIndex >= _endIndex) { return; }   // 재귀함수 끝내는 조건
 
        int pivotIndex = _startIndex;                // 기준 데이터는 첫번째 데이터
        int leftIndex  = _startIndex + 1;            // 왼쪽 다음부터 비교 시작
        int rightIndex = _endIndex;                    // 마지막 데이터
        
        // 양 끝의 인덱스 값이 교차할떄가지 반복
        while (leftIndex <= rightIndex)
        {
            // 왼쪽값들로부터 기준 데이터보다 큰 값을 찾음
            while (leftIndex <= _endIndex && _arr[leftIndex] <= _arr[pivotIndex])
            { leftIndex++; }
            
            // 오른쪽값들로부터 기준 데이터보다 작은 값을 찾음
            while (rightIndex > _startIndex && _arr[rightIndex] >= _arr[pivotIndex])
            { rightIndex--; }
            
            // 만약 인덱스 값이 교차할 경우 rightIndex의 값을 기준 데이터와 바꾸고 While문 종료 
            if (leftIndex > rightIndex)
            {
                int temp         = _arr[rightIndex];
                _arr[rightIndex] = _arr[pivotIndex];
                _arr[pivotIndex] = temp;
            }
            else
            {    // 아닐 경우 왼쪽 값과 오른쪽 값을 바꿈 다시 반복
                int temp         = _arr[rightIndex];
                _arr[rightIndex] = _arr[leftIndex];
                _arr[leftIndex]  = temp;
            }
        }
        
        MyQuickSort(_arr, _startIndex, rightIndex - 1);        // rightIndex 값을 기준으로 분할되어 endIndex를     새로운 기준 데이터 인덱스의     -1 왼쪽 정렬
        MyQuickSort(_arr, rightIndex + 1, _endIndex);        // rightIndex 값을 기준으로 분할되오 startIndex를 새로운 기준 데이터 인덱스의     +1 한 후 오른쪽 정렬
    }
}
cs