Quick Sort는 분할 정복(divide and conquer)방법을 통해 주어진 배열을 정렬한다.
[분할 정복 방법]
문제를 작은 2개의 문제로 분리하고 각각을 해결한 다음, 결과를 모아서 원래의 문제를 해결하는 전략이다.
Quick Sort는 불안정 정렬에 속하며, 다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속한다. Merge Sort와 달리 Quick Sort는 배열을 비균등하게 분할한다.
void quickSort(int[] arr, int left, int right) {
if(left >= right) {
return;
}
// 분할
int pivot = partition();
// 피벗을 제외한 2개의 부분 배열을 대상으로 재귀 호출
quickSort(arr, left, pivot-1); // 정복
quickSort(arr, pivot+1, right); // 정복
}
int partition(int[] arr, int left, int right) {
int pivot = arr[left]; // 가장 왼쪽 값을 피벗으로 설정
int i = left;
int j = right;
while(i < j) {
while(pivot < arr[j]) {
j--;
}
while(i < j && pivot >= arr[i]) {
i++;
}
swap(arr, i, j);
}
arr[left] = arr[i];
arr[i] = pivot;
return i;
}
비교 횟수(log₂n)
레코드의 개수 n이 2의 거듭제곱이라고 가정했을 때, n=2^3의 경우 2^3 -> 2^2 -> 2^1 순으로 줄어들어 순환 호출의 깊이가 3임을 알 수 있다.
위 공식을 일반화하면 n=2^k일 경우, k(k=log₂n)임을 알 수 있다.
최악의 경우
최악의 경우는 정렬하고자 하는 배열이 오름차순 정렬되어있거나 내림차순 정렬 되어있는 경우다.
따라서 최악의 시간복잡도는 순환 호출의 깊이 * 각 순환 호출 단계의 비교 연산 = n^2
다. 이동 횟수는 비교 횟수보다 적으므로 무시할 수 없다.
주어진 배열 안에서 교환을 통해, 정렬이 수행되므로 O(n)이다.