백준 사다리 문제에서 다뤘던 삽입정렬과 버블 정렬을 제외하고
나머지 정렬 알고리즘에 대해 정리하고 직접 구현해보려고 한다

퀵 정렬은 벗을 하나 두고 두개의 부분리스트로 나누어서 정렬하는 방식이다
피벗의 왼쪽에는 피벗보다 작은 값들이 있고 오른쪽은 피벗보다 큰 값들이 존재한다
이 방식으로 재귀적으로 수행하여 정렬하는 것이 퀵 정렬이다
퀵정렬은 피벗을 왼쪽, 가운데, 오른쪽 중 하나에 두고 정렬을 할 수 있다
각 방식에 따라 방식이 조금씩 달라진다.
public class QuickSort{
private static void leftPivotQuickSort(int[] arr, int low, int high){
if(low >= high){
return;
}
int pivot = leftPartitioning(arr, low, high);
leftPivotQuickSort(arr, low, pivot-1);
leftPivotQuickSort(arr, pivot+1, high);
}
private static void rightPivotQuickSort(int[] arr, int low, int high){
if(low >= high){
return;
}
int pivot = rightPartitioning(arr, low, high);
rightPivotQuickSort(arr, low, pivot -1);
rightPivotQuickSort(arr, pivot+1, high);
}
private static void centerPivotQuickSort(int[] arr, int low, int high){
if(low >= high){
return;
}
int pivot = centerPartitioning(arr, low, high);
centerPivotQuickSort(arr, low, pivot);
centerPivotQuickSort(arr, pivot+1, high);
}
private static int centerPartitioning(int[] arr, int left, int right){
int low = left -1;
int high = right + 1;
int pivot = arr[(left + right) / 2];
while(true){
do{
low++;
}while(arr[low] < pivot);
do{
high--;
}while(arr[high] > pivot && low <= high);
if(low >= high){
return high;
}
swap(arr, low, high);
}
}
private static int leftPartitioning(int[] arr, int left, int right){
int low = left;
int high = right;
int pivot = arr[left];
while(low < high){
while(arr[high] > pivot && low < high){
high--;
}
while(arr[low] <= pivot && low < high){
low++;
}
swap(arr, low, high);
}
swap(arr, left, low);
return low;
}
private static int rightPartitioning(int[] arr, int left, int right){
int low = left;
int high = right;
int pivot = arr[right];
while(low < high){
while(arr[low] < pivot && low < high){
low++;
}
while(arr[high] >= pivot && low < high){
high--;
}
swap(arr, low, high);
}
swap(arr, right, high);
return high;
}
private static void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
위 코드는 피벗을 왼쪽, 오른쪽, 가운데에 넣고 정렬하는 코드이다
왼쪽과 오른쪽은 비슷하다
1 . 피벗을 하나 선택하고, low에는 왼쪽, high에는 오른쪽 위치를 넣어준다
2 . 공통적으로 low가 high보다 작아야하고 (엇갈리거나 만나지 않아야하고),
pivot보다 low 위치에 있는 값이 작다면 low를 증가시킨다
3 . 이어서 pivot보다 high 위치에 있는 값이 크거나 같다면 high를 감소시킨다
4 . 위 과정이 끝나면 low와 high를 바꿔준다.
5 . 이것을 low가 high보다 작은동안 반복하며,
모두 끝난 뒤에는 left와 low 또는 right와 high를 swap하고 각각 low와 high를 pivot으로 리턴한다
6 . pivot을 기준으로 다시 분할하여 왼쪽과 오른쪽에 대해 재귀적으로 다시 정렬한다
가운데를 pivot으로 두는 경우 left와 right를 범위 밖에 두고 left와 right순서대로 위 왼쪽/오른쪽 과정을 반복한다
만약 left와 right가 엇갈린다면 그대로 right 값을 넘겨준다.
이어서 다시 나뉜 left와 right를 재귀적으로 정렬해주면 된다
일반적으로 최선의 경우와 평균적인 경우 O(nlogn) 시간복잡도가 발생하며,
비슷한 시간복잡도의 다른 정렬과 비교했을 때, 대체적으로 시간이 빠르다
하지만 왼쪽/오른쪽 기준을 잡고 정렬하는 경우,
이미 정렬되어 있는 배열을 마주쳤을 때 최악의 시간복잡도 O(n^2)이 발생한다.
따라서 일반적으로는 가운데를 기준으로 잡고 정렬하는 것이 선호된다는 것을 참고하자!