네. 저번주에 포스팅 하는 걸 잊었습니다.
... 그래서 이제부터 일주일 내내 하나씩 포스팅하기로 약속했습니다.
- Matrix 때문에 지금 Dlbo 군에게 열심히 갈굼당하고 있습니다. -_- 이건 그것도 겸한거죠. -
큼... 각설하고.
이번 포스팅 주제는 Quick Sort 알고리즘입니다.
정렬 알고리즘 중 가장 효율적이고 사용 빈도가 높은 알고리즘 중 하나입니다.
- C 언어 라이브러리 함수로 qsort() 라는게 있습니다. Quick Sort 를 라이브러리화 해 놓은 거라
쉽게 사용이 가능합니다. 이것도 이유가 될 수 있겠죠. 비교 함수만 하나 더 만들어 주면 끝이거든요. -
흠... 일단 Quick Sort 를 소개하려면 'Divide and conquer' 라는 알고리즘 기법부터 설명해야 할까요.
'재귀' 라는 말은 한번쯤 들어 보셨겠죠?
쉽게 말해 자기 자신과 같은 일을 몇 번이고 계속 하는 구조를 일컬어 '재귀 구조' 라 합니다.
보통 '재귀'라 하면 재귀 함수를 생각하시는 분들이 많을 겁니다.
하지만, 여기서 말하고자 하는 재귀 구조는 '재귀 함수' 가 아닙니다.
- 물론, 우리가 Quick Sort를 구현할 때 재귀 함수를 쓰긴 합니다. -
단지 방법론적인 측면의 이야기를 하고 있죠.
즉, 주어진 문제를 해결하기 위해 전체의 큰 틀을 상정하고, 전체와 유사한 구조를 가지는 작은 틀들로
이 문제를 쪼갭니다.
그 후 재귀 구조를 이용, 이 작은 틀들을 기준으로 문제를 풀고, 다시 재결합하는 것이죠.
이 작은 틀은 전체 구조와 거의 유사한 구조를 가지고 있으므로, 이들을 '해결한다.' 라는 의미는
'전체 문제를 해결한다.' 라는 말과 같은 뜻이 될 겁니다.
이것이 분할 정복 - Divide and conquer - 기법이죠.
Quick Sort 알고리즘은 이 Divide and conquer 기법의 대표적인 예입니다.
자, 이제 알고리즘 소개를 해 볼까요.
2. 기준치를 중심으로 기준치보다 작은 수들은 왼쪽 배열에 대입한다.
3. 기준치를 중심으로 기준치보다 큰 수들은 오른쪽 배열에 대입한다.
4. 왼쪽 배열에 대해 1. 2 . 3 번 알고리즘을 계속 반복한다.
5. 더이상 바꿀 수가 없다면 오른쪽 배열에 대해 탐색한다.
6. 오른쪽 배열에 대해 1. 2. 3번 알고리즘을 반복한다.
7. 더이상 바꿀 수가 없다면. -> 정렬 종료.
한 눈에 보기에도 재귀 구조가 존재한다는 것을 알 수 있으실 겁니다.
알고리즘의 소개가 끝났으니, 소스 코드를 써 볼까요.
직접 구현을 할 수도 있겠지만, 일단은 라이브러리 함수를 사용하겠습니다.
혹시 Quick Sort 의 구현을 보고 싶으시다면 알려주세요.
이제까지처럼 10개의 레코드를 정렬하는코드입니다.
qsort 함수의 호출을 위해서는 인자 4개를 넘겨줘야 합니다. 순서대로 나열하죠.
- 포함 헤더파일.
stdlib.h
- 호출인자.
1.정렬할 배열.
2. 정렬할 배열의 크기.
3. 정렬할 배열의 데이터 크기.
- sizeof 함수를 이용합시다. -
4. 비교함수 식별자.
-사용자가 만들어 줍니다. 만약 위 코드와 달리 내림차순 정렬을 하고 싶다면 다음과 같이 비교함수를 만들어 주시면 됩니다. -
이제 성능 분석입니다.
직접 구현을 해 보면 아시겠지만, Quick Sort 는 기준치를 어떻게 잡냐에 따라 성능이 차이가 납니다.
일반적으로 가장 최악의 성능을 가질 때는 기준치가 각 케이스별로 배열의 first index 이거나 last index 일 경우입니다.
이 경우 평균 O(N^2) 의 시간복잡도를 가지게 된다는 것이 알려져 있습니다.
물론 최악의 경우만 놓고 보면 앞서 언급했던 알고리즘들과 성능차가 크게 나지 않습니다.
하지만 라이브러리 함수는 세 값의 중위법 - Three of Median - 을 이용합니다.
- 세 값의 중위법이란 배열의 first index 와 last index, 그리고 이 값의 중간값인 (first + last) / 2 의 세 값을 이용한 기법이죠. -
이 경우엔 분할이 거의 중앙에서 이루어지므로 재귀의 깊이가 대폭 줄어들게 됩니다.
평균적으로 O(N * log N) 의 시간복잡도를 갖게 되죠.
그러므로, 일반적으로 Quick Sort, 특히 라이브러리 함수를 이용하게 되면 시간복잡도 상한 O(N * log N)의
시간 안에 효율적으로 정렬을 할 수 있다는 것을 알 수 있습니다.
'(탈퇴) Reuent's Post > Algorithms' 카테고리의 다른 글
Algorithm #1. Sort algorithm. - 1.6 Radix Sort algorithm. (0) | 2010.03.04 |
---|---|
Algorithm #1. Sort algorithm. - 1.5 Heap Sort algorithm. (0) | 2010.03.04 |
Algorithm #1. Sort algorithm. - 1.3 Bubble Sort algorithm. (0) | 2010.03.04 |
Algorithm #1. Sort algorithm. - 1.2 Insertion Sort algorithm. (0) | 2010.03.04 |
Algorithm #1. Sort algorithm. - 1.1 정렬 알고리즘의 필요성, 그리고 알려진 알고리즘의 종류와 일반적 특성. (1) | 2010.03.04 |