퀵소트란?

0️⃣1️⃣·2021년 5월 5일
0

알고리즘

목록 보기
4/9

퀵소트?

  • 배열을 피벗을 기준으로 나눠서 정렬하는 방식

  • 피벗을 어떻게 선택함에 따라, 성능 차이가 존재

  • 최악의 경우 O(n^2)까지 발생할 수 있음

  • 베스트 케이스의 경우 O(nlogn)의 시간 복잡도를 가짐

  • 공간복잡도는 O(logn), 퀵소트의 재귀적 호출때문에 호출 스택 공간이 필요

  • 최악의 경우 O(n^2)이지만, Java의 팀소트에 퀵소트를 쓰는 이유는 참조 지역성의 원리때문

두 포인터를 이용한 구현방법?

  • 피벗을 선택하고, 피벗과의 값 비교를 통해서 왼쪽과 오른쪽 포인터가 가르키는 값을 스왑

  • 두 포인터가 겹치게 되면, 종료

  • 베이스 케이스 처리가 중요(원소가 1개 혹은 2개인 경우)

하나의 포인터를 이용한 구현방법?

  • 첫번째 원소를 피벗으로 선택하고, 첫번째 원소를 제외한 배열의 값들을 비교

  • 포인터가 지난 값들은 모두, 피벗보다 작은 값이 된다.

  • 포인터가 멈춰있는 경우에는, 피벗보다 큰 값이 된다.

  • 모든 배열의 값이 탐색되면, 포인터의 뒤에는 피벗보다 작은 값들만 존재한다.

코드?

class Solution {
    void quickSort(int[] nums, int start, int end){
    	// 하나의 포인터를 이용한 구현방법
        if(start >= end)
            return;
        
        int pivot = nums[start];
        int p = start + 1;
        
        for(int i = start + 1; i <= end; i++){
            if(nums[i] <= pivot){
                swap(nums, p, i);
                p++;
            }    
        }
        swap(nums, start, p - 1);

        quickSort(nums, start, p - 2);
        quickSort(nums, p, end);
    }
    
    void quickSort2(int[] nums, int start, int end){
    	// 두 포인터를 이용한 구현방법
        if(start >= end)
            return;
        
        int s = start;
        int e = end;
        int pivot = nums[start];
        
        while(s < e){
            while(s <= e && nums[s] <= pivot) s++;
            while(e >= s && nums[e] > pivot) e--;
            
            if(s <= e){
                swap(nums, s, e);
            }
        }
        swap(nums, start, e);

        quickSort2(nums, start, e - 1);
        quickSort2(nums, e + 1, end);
    }
    
    void swap(int[] nums, int idx1, int idx2){
        int tmp = nums[idx1];
        nums[idx1] = nums[idx2];
        nums[idx2] = tmp;
    }
    
    public int[] sortArray(int[] nums) {
        quickSort2(nums, 0, nums.length - 1);
        return nums;
    }
}

0개의 댓글