알고리즘 공부

[정렬] 퀵정렬 (Quick Sort) - Java

Developer KTU 2024. 9. 7. 18:12
반응형

1. 개요

퀵 정렬(Quick Sort)은 피벗을 하나 정하고, 배열을 피벗을 기준으로 배열을 분할하여 정렬하는 기법이다. 재귀 호출을 사용한다.

 

 

2. 시간복잡도

어떤 피벗값을 선정하는지에 따라 시간복잡도 차이가 난다.

평균 시간복잡도 : 𝛳(nlogn)

최악 시간복잡도 : O(n^2)

 

 

3. 핵심이론

1) 하나의 피벗(기준값)을 정한다. (피벗값 배열의 맨 처음 값으로 설정)

2) 시작, 끝 포인터를 설정한다. (시작 s는 0, 끝 e는 배열의 마지막 인덱스로 설정한다.)

3) s가 e보다 작을 때까지 순회한다.

    3-1) 배열의 마지막 값 (arr[e])이 피벗값 (arr[pivot]) 보다 클때 까지 순회하며, e를 1씩 왼쪽(감소)으로 이동한다.

            (피벗값보다 작은 값이 나올때까지 순회)

    3-2) 배열의 처음 값.(arr[s]) 이 피벗값 (arr[pivot]) 보다 작을때까지 순회하며, s를 1씩 오른쪽 (증가)로 이동한다.

            (피벗값보다 큰 값이 나올때까지 순회)

    3-3) arr[s]이 arr[pivot] 보다 크고, arr[e]이 arr[pivot]보다 작으면, 두 위치를 swap 한다.

4) 위 loop를 빠져왔다면, s와 e 두 포인터가 만났다는 의미이므로, s 또는 e 포인터와 pivot을 swap한다.

5) 그 결과, pivot 기준 왼쪽엔 arr[pivot] 보다 작은 값들이, 오른쪽엔 arr[pivot] 보다 큰 값들이 정렬된다.

6) pivot 기준 왼쪽 부분 배열과 오른쪽 부분배열을 다시 퀵정렬한다. (재귀 호출)

 

 

3. 예제 코드

public class Main {
    // 퀵정렬 수행 함수
    public static void quickSort(int[] arr, int start, int end){
        // 배열의 크기가 1이거나, 정렬을 수행할 배열이 더이상 없다면 재귀 호출 종료
        if(start >= end){
            return;
        }

        // pivot 위치를 구하는 partition 함수
        int pivot = partition(arr, start, end);

        // 구한 pivot을 기준으로 왼쪽 부분배열과 오른쪽 부분배열을 다시 퀵정렬 수헹 (재귀)
        quickSort(arr, start, pivot - 1);
        quickSort(arr, pivot + 1, end);
    }

    public static int partition(int[] arr, int start, int end){
        // 피벗은 배열의 첫번째 위치로 설정
        int pivot = start;
        // 처음, 끝 포인터 초기화
        int s = start;
        int e = end;

        // s가 e보다 왼쪽에 있을때 까지 loop (s와 e가 만나면 loop 종료)
        while(s < e){
            // 마지막 값이 피벗값보다 작은 값이 나올때 까지 loop
            while(arr[e] > arr[pivot] && s < e){
                // 마지막 위치를 왼쪽으로 이동
                e--;
            }
            // 처음 값이 피벗값보다 큰 값이 나올때 까지 loop
            while(arr[s] <= arr[pivot] && s < e){
                // 처음 위치를 오른쪽으로 이동
                s++;
            }

            // 처음 값이 피벗값보다 크고, 마지막 값이 피벗값보다 작으면 두 위치를 swap
            swap(arr, s, e);
        }

        // 위 while문을 빠져나왔다는 의미는 s와 e가 만났다는 의미이므로, 맨 처음 위치에 있는 pivot값과 두 포인터가 만난 s값과 swap
        swap(arr, pivot, s);

        // s와 e가 만난 지점 (둘 중 하나)을 반환
        return s;
    }

    // swap 함수
    public static void swap(int[] arr, int t1, int t2){
        int temp = arr[t1];
        arr[t1] = arr[t2];
        arr[t2] = temp;
    }
	
    // 메인 함수
    public static void main(String[] args) {
        int[] arr = {-7, 1, -3, 10, 7};

        // 주어진 배열에 대해 퀵정렬 수행
        quickSort(arr, 0, arr.length - 1);

        for (int i : arr) {
            System.out.print(i + " ");
        }
    }
}
반응형