Quick Sort는 분할 정복(divide and conquer) 방법 을 통해 주어진 배열을 정렬합니다.
Quick Sort는 불안정 정렬에 속하며, 다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속합니다. 또한 Merge Sort와 달리 Quick Sort는 배열을 비균등하게 분할합니다.
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
lesser_arr, equal_arr, greater_arr = list(), list(), list()
for num in arr:
if num < pivot:
lesser_arr.append(num)
elif num > pivot:
greater_arr.append(num)
else:
lesser_arr.append(num)
return quick_sort(lesser_arr) + equal_arr + quick_sort(greater_arr)
피봇 값이 최소나 최대값으로 지정되어 파티션이 나누어지지않는 경우 O(n^2)에 대한 시간복잡도를 가집니다. 즉, 정렬하고자 하는 배열이 오름차순으로 정렬되어있거나 내림차순으로 정렬되어있으면 O(n^2)의 시간복잡도를 가집니다. 이때, 배열에서 가장 앞에 있는 값과 중간 값을 교환해준다면 확률적으로나마 시간복잡도 O(nlogn)으로 개선할 수 있습니다.
순환 호출의 깊이
레코드의 개수 n이 2의 거듭제곱이라 가정했을 때 순환 호출의 깊이는 logn이 됩니다.
각 순환 호출 단계의 비교 연산
각 순환 호출에서는 전체 리스트의 대부분의 레코드를 비교해야 하므로 평균 n번 정도의 비교가 이루어집니다.
따라서, 최선의 시간복잡도는 순환 호출의 깊이 * 각 순환 호출 단계의 비교 연산 = nlog2
이 됩니다.
최악의 경우는 정렬하고자 하는 배열이 오름차순 정렬되어있거나 내림차순으로 정렬되어 있는 경우입니다.
레코드의 개수 n이 2의 거듭제곱이라고 가정(n=2^k)했을 때, 순환 호출의 깊이는 n 임을 알 수 있습니다.
따라서, 최악의 시간복잡도는 순환 호출의 깊이 * 각 순환 호출 단계의 비교 연산 = n^2
주어진 배열 안에서 교환(swap)을 통해, 정렬이 수행되므로 O(n) 이다.