| ||
| ||
![]() | ||
![]() |
|
|
![]() |
퀵 정렬을 정의하면 다음과 같습니다.
① 분할
리스트에서 피봇(pivot) 키의 원소를 선택하여 리스트를 다음과 같이 분할한다.
- 피봇 키의 값보다 작은 키를 가진 원소들을 피봇 키 원소보다 앞에 둔다.
- 피봇 키의 값보다 큰 키를 가진 원소들은 피봇 키 원소보다 뒤에 둔다.
② 재귀적 퀵 정렬 : 피봇 키의 원소 앞뒤의 부 리스트들에 각각 퀵 정렬을 수행한다.
퀵 정렬도 말로 설명을 하는 것보다 우선 예제를 보고 손으로 먼저 해 보는 것이 좋습니다.
퀵 정렬은 피봇라는 데이터를 하나 정하고, 입력 데이터를 피봇 데이터보다 큰 것과 작은 것으로 분할하는 분할 작업이 주된 작업입니다. 분할 작업이 한번 수행되면 피봇 앞에 있는 데이터는 피봇보다 큰 것이고, 피봇 뒤에 있는 것은 피봇보다 작은 데이터들이 모입니다. 이렇게 분할 된 데이터는 다시 각각을 분할 작업을 수행하게 됩니다. 만약 분할된 리스트의 데이터 수가 2라면 이는 두 데이터만을 비교하고 교환하여 정렬할 수 있습니다. 더 이상 분할할 리스트가 없을 때까지 수행되는데 이는 재귀적으로 수행할 수 있습니다.
이를 코딩으로 나타내 볼까요? 우선 퀵 정렬을 재귀적으로 호출하는 것부터 해봅시다. 재귀적으로 호출한다는 것은 자신을 다시 호출한다는 거죠? 피봇 데이터가 리스트에서 들어갈 위치가 j라고 한다면, 피봇보다 작은 데이터들의 리스트와 피봇보다 큰 데이터들의 리스트를 다시 퀵 정렬의 입력으로 넣기만 하면 됩니다. 퀵 정렬의 입력 데이터의 위치가 left~ right까지 이었다면 다음처럼 나타낼 수 있습니다.
QuickSort(left, j-1);
QuickSort(j+1, right);
그럼 피봇 데이터가 들어갈 위치를 찾는 것은 어떻게 할까요? 퀵 정렬의 분할 알고리즘의 두 조건 생각나죠? 이 두 조건을 수행하기 위해서 while문을 수행합니다. 그러면 다음처럼 나타낼 수 있습니다.
// 리스트의 제일 처음 데이터부터 피봇 데이터보다 큰 값인 데이터를 찾는다.
do i++;
while(i
do j--;
while(j>left && data[j] > pElement);
그럼 이젠 퀵 정렬을 분석해 보겠습니다. 퀵 정렬의 최악의 경우는 리스트가 역순으로 정렬되어 있는 경우입니다. 왜냐하면, 역순으로 정렬된 경우에는 분할을 n -1번 수행해야 하고, i번째 분할에서 비교횟수는 n -i 가 되기 때문입니다. 따라서 총 비교횟수는 다음과 같습니다.
( n - 1) + ( n - 2) + ··· + 2 + 1 = n ( n - 1) ①
2
수치 정렬 정리
이번 호에서 살펴본 세 가지 정렬 알고리즘인 버블, 삽입, 퀵 정렬의 성능을 비교해보는 일이 남았습니다. 세 정렬을 살펴볼 때 이미 각각의 알고리즘의 성능 분석을 했습니다. 다시 살펴볼까요?
모두 앞의 ①이라고 되어 있습니다. 그러면 세 알고리즘의 성능이 모두 같다는 말일까요? 다시 살펴보면 버블 정렬의 경우는 항상 만큼의 수행시간이 필요합니다. 삽입 정렬과 퀵 정렬의 경우에는 입력된 데이터가 역순일 경우에
만큼의 수행시간이 필요합니다. 따라서 일반적인 데이터일 경우에는 버블 정렬보다는 삽입 정렬이나 퀵 정렬이 빨리 수행된다고 볼 수 있습니다. 하지만 데이터가 작을 경우에는 버블 정렬이 더 빠를 수 있으며, 퀵 정렬의 경우 함수를 재귀적으로 호출해야하기 때문에 시간이 더 걸립니다. 요즘 우리가 사용하는 컴퓨터의 성능으로는 작은 데이터에서 각 알고리즘의 시간 차이를 알 수가 없습니다. 하지만 국가 차원에서 다루는 데이터나 기업, 학교 같이 대용량의 데이터를 다루는 곳에서는 어떤 알고리즘을 사용하느냐에 따라 시간차이가 나므로 자신에게 알맞은 알고리즘을 사용해야겠습니다.
모든 알고리즘 코딩을 직접?
프로그램을 개발할 때 기초가 되는 자료구조나 알고리즘을 모두 코딩해서 사용하는 것은 작성하는 프로그램 오류를 증가시킬 수 있습니다. 물론 이번 호에서 살펴본 간단한 알고리즘이나 자신이 개발하거나 수정한 알고리즘 같은 경우는 코딩을 하겠지만, Red-Black Tree와 같이 복잡한 자료구조를 사용할 때에는 능숙한 프로그래머라도 실수를 할 수 있습니다. 실수를 하지 않더라도 개발 시간이 많이 걸리겠죠? 이렇게 직접 구현하는 것보다 이미 구현되어 있는 검증된 라이브러리를 이용하는 것이 효율적일 수 있습니다. 현재 전 세계적으로 많은 알고리즘들이 라이브러리화되어 있지만, STL, 알고리즘 리파지토리와 같은 라이브러리가 많이 사용되는 라이브러리입니다. 이중 LEDA는 많은 자료구조와 알고리즘이 구현되어 있습니다. 물론 알고리즘이나 자료구조를 배우고 있는 학생이라면 한번쯤은 코딩을 하는 것이 좋은 경험이 될 것입니다.
이번 호를 보면서 ‘너무 쉬워’라고 생각한 독자도 있을 것입니다. 하지만 이번 연재는 처음 알고리즘이라는 것을 접하고 이를 어떻게 해결해야 할까를 고민하는 독자를 대상으로 한 것이므로 이러한 독자들에게는 많은 도움이 되었기를 바랍니다
'고니의사진방' 카테고리의 다른 글
| [쩐의전쟁] 뮤비 - 심플라이프 (0) | 2007/06/14 |
|---|---|
| Phishing Attacks (0) | 2007/06/14 |
| 기초부터 차근차근 ‘정렬 알고리즘’ (0) | 2007/06/08 |
| 사돌이 사순이 빈볼시비 (0) | 2007/06/01 |
| 유리잔 연주 (0) | 2007/04/22 |
| 바나나폰 CF (0) | 2007/04/21 |
TAG 정렬







댓글을 달아 주세요