퀵 정렬 알고리즘이란?
선정된 pivot값을 기준으로 배열을 나누어가면서 재귀적으로 정렬하는 알고리즘
알고리즘 설계 전략
pivot을 선정한다.
pivot 보다 작은 값은 왼쪽, 더 큰 값은 오른쪽에 배치한다.
양쪽 배열에 대해 다시 같은 과정을 반복함으로써 최종적으로 배열을 정렬한다.
알고리즘 수도코드
void quicksort(index low, index high) {
index pivotpoint;
if(high > low) {
partition(low, high, pivotpoint); //배열을 pivot 값을 기준으로 반으로 나눈다.
quicksort(low, pivotpoint-1); // 왼쪽 배열에 대해 재귀적으로 정렬
quicksort(pivotpoint+1,high); // 오른쪽 배열에 대해 재귀적으로 정렬
}
}
void partition (index low, index high, index& pivotpoint) {
index i, j;
keytype pivotitem;
pivotitem = s[low];
j = low;
for(i=low+1 ; i<=high ; i++)
if(s[i] < pivotitem) { //pivot 값보다 작으면 왼쪽에 배치, ①
j++;
exchange s[i] and s[j];
}
pivotpoint = j;
exchange s[low] and s[pivotpoint]; //pivot 값보다 크면 오른쪽에 배치, ②
}
partipation 함수의 동작 원리는 다음과 같다.
알고리즘 성능 분석
basic operation : 배열 원소와 pivot과의 비교(위 코드 ①, ② 부분)
quicksort 함수와 participation 함수 각각 따로 알아보자.
participation 함수 성능분석
participation 함수에서는 pivot값과 나머지 배열 원소들 간의 비교가 이루어지므로 every-case이다.
배열 크기를 n이라고 할 때, pivot을 제외한 나머지 배열 원소들의 수는 n - 1이므로 T(n) = n - 1이다.
∴T(n) = n - 1
quicksort 함수 성능분석
quicksort 함수는 participation 함수와 달리 every-case가 아니다. best-case/worst-case가 존재한다.
그렇다면, 어떤 경우에 worst-case일까? 먼저 아래 그림의 경우를 살펴보자.
위 그림처럼 배열의 값이 이미 크기순으로 정렬된 경우, 매번 정렬 결과 pivot이 배열의 맨 끝에 온다. 즉, pivot 값이 배열의 다른 원소들보다 제일 작거나 큰 경우 이런 상황이 발생하는데 이렇게 pivot이 맨 끝에 오게되면 매번 배열이 왼쪽, 오른쪽 이렇게 두 배열로 나눠지는 것이아니라, 왼쪽 혹은 오른쪽 둘 중 하나의 배열로만 나눠진다. 따라서 재귀 호출 횟수가 줄어들어 최악의 경우가 된다.
쉽게말하면, 배열이 두 덩이로 나뉘지 않고 지속적으로 한 덩이로 나뉘는 것이 최악의 경우가 된다는 말이다. 이 말은, 매 정렬마다 생겨나는 pivot의 수가 많을수록 좋다는 뜻이기도 하다.
위 내용을 토대로 최악의 경우에 대한 점화식을 세워보면
w(n) = w(한 쪽 원소개수 0 개) + w(나머지 원소개수 n-1개) + participation 함수의 시간복잡도(= every-case)
= w(0) + w(n - 1) + n - 1
∴ w(n) = w(0) + w(n - 1) + n - 1
위 점화식을 일반화해보면
T(n) = T(n - 1) + n - 1 |
T(n - 1) = T(n - 2) + n - 2 |
T(n - 2) = T(n - 3) + n - 3 |
. . . |
T(2) = T(1) + 1 |
T(1) = T(0) + 0 |
T(0) = 0 |
w(n)=1 + 2 + 3 + ... n - 1 = n(n - 1)/2 ∈ Θ(n2)
∴ w(n) ∈ Θ(n2)
'알고리즘 > <2> Divide-and-Conquer' 카테고리의 다른 글
[알고리즘] 합병 정렬, Merge Sort | 설계 및 분석 (0) | 2020.12.28 |
---|---|
[알고리즘] 이진탐색, Binary Search | 설계 및 분석, 구현코드 (0) | 2020.12.28 |
[알고리즘] 분할정복, Divide-and-Conquer (0) | 2020.12.26 |