자료 구조 - 정렬 1
1. 퀵 정렬
- 정렬할 전체 원소에 대해서 정렬을 수행하지 않고 기준 값을 중심으로 왼쪽 부분 집합과 오른쪽 부분 집합으로 분할하여 정렬
1) 수행 방법
- 왼쪽 부분 집합에는 기준 값보다 작은 원소들을 이동시키고, 오른쪽 부분 집합에는 기준 값보다 큰 원소들을 이동시킴
- 기준 값 : 피봇(pivot)
- 일반적으로 전체 원소 중에서 가운데에 위치한 원소를 선택
2) 개요
(1) 분할 (divide)
- 정렬할 자료들을 기준 값을 중심으로 2개의 부분 집합으로 분할
(2) 정복 (conquer)
- 부분 집합 원소들 중에서 기준 값보다 작은 원소들은 왼쪽 부분 집합으로, 기준 값보다 큰 원소들은 오른쪽 부분집합으로
정렬
- 부분 집합의 크기가 1 이하로 충분히 작지 않으면 순환 호출을 이용하여 다시 분할
3) 수행 방법
(1) 부분 집합으로 분할하기 위해 L과 R을 사용
- 왼쪽 끝에서 오른쪽으로 움직이면서 크기를 비교하여 피봇보다 크거나 같은 원소를 찾아 L로 표시
- 오른쪽 끝에서 왼쪽으로 움직이면서 피봇 보다 작은 원소를 찾아 R로 표시
- L이 가리키는 원소와 R이 가리키는 원소를 서로 교환함
(2) L이 R이 만나게 되면
- 피봇과 R의 원소를 서로 교환
- 교환한 위치를 피봇의 위치로 확정함
(3) 피봇의 확정된 위치를 기준으로 잡음
- 만들어진 새로운 왼쪽 부분 집합과 오른쪽 부분 집합에 대해서 퀵 정렬을 순환적으로 반복 수행함
- 모든 부분 집합 크기가 1 이하가 되면 퀵 정렬을 종료
4) 수행 과정
- 정렬 되지 않은
{69,10,30,2,16,8,31,22}
의 자료들을 퀵 정렬 방법으로 정렬하는 과정
- 원소의 개수가 8개이므로 네 번째 자리에 있는 원소
2
를 첫 번째 피봇으로 선택하고 퀵 정렬 시작
(1) 원소 2
를 피봇으로 선택하고 퀵 정렬 시작
- L이 오른쪽으로 이동하면서 피봇 보다 크거나 같은 원소를 찾음
- R이 왼쪽으로 이동하면서 피봇보다 작은 원소를 찾음
- L은 원소
69
를 찾았지만, R은 피봇 보다 작은 원소를 찾지 못한 채로 원소 69
에서 L과 만나게 됨
- L과 R이 만났으므로, 원소
69
를 피봇과 교환하여 피봇 원소 2의 위치를 확정함
(2) 피봇 2
의 왼쪽 부분 집합은 공집합
- 피봇
2
의 왼쪽 부분 집합은 공집합이므로 퀵 정렬을 수행하지 않음
- 오른쪽 부분 집합에 대해서 퀵 정렬 수행
- 오른쪽 부분 집합의 원소가 7개 이므로 가운데 있는 원소
16
을 피봇으로 선택
- L이 찾은
30
과 R이 찾은 8
을 서로 교환 함
- 현재 위치에서 L과 R의 작업을 반복함
- L은 원소
69
를 찾았지만, R은 피봇보다 작은 원소를 찾지 못한 채로 원소 69
에서 L과 만나게 됨
- L과 R이 만났으므로, 원소
69
를 피봇과 교환하여 피봇 원소 16
위치를 확정함
(3) 원소 10
을 피봇으로 선택하여 퀵 정렬 수행
- 피봇
16
의 왼쪽 부분 집합에서 원소 10
을 피봇으로 선택하여 퀵 정렬 수행
- L의 원소
10
과 R의 원소 8
을 교환
- L의 원소가 피봇이므로 피봇원소에 대한 자리교환이 발생한 것이므로 교환한 자리를 피봇 원소
10
의 위치로 확정
(4) 피봇 10
의 확정된 위치에서의 왼쪽 부분 집합은 원소가 한개
- 피봇
10
이 확정된 위치에서의 왼쪽 부분 집합은 원소가 한개 이므로 퀵정렬 수행 하지 않음
- 오른쪽 부분 집합은 공집합이므로 퀵 정렬 수행 않음
- 이제 1단계의 피봇이었던 원소
16
에 대한 오른쪽 부분 집합에 대해 퀵 정렬을 수행
- 오른쪽 부분 집합의 원소가 4개이므로 두 번째 원소
30
을 피봇으로 선택
- L이 찾은
69
와 R이 찾은 22
를 서로 교환
- 현재 위치에서 L과 R의 작업를 반복
- L은 오른쪽으로 이동하면서 피봇 보다 크거나 같은 원소인
30
을 찾음
- R은 왼쪽으로 이동하면서 피봇 보다 작은 원소를 찾다가 못 찾고 원소
30
에서 L과 만남
- L과 R이 만났으므로 피봇과 교환
- 이경우는 R의 원소가 피봇이므로 피봇에 대한 자리 교환이 발생한 것이므로 교환한 자리를 피봇의 자리로 확정
(5) 피봇 30
의 확정된 위치에서의 왼쪽 부분 집합의 원소가 한 개
- 피봇
30
의 확정된 위치에서의 왼쪽 부분 집합의 원소가 한 개 이므로 퀵정렬 수행 않음
- 오른쪽 부분 집합에 대해서 퀵 정렬 수행
- 오른쪽 부분 집합의 원소 2개 중에서 원소
31
을 피봇으로 선택
- L은 오른쪽으로 이동하면서 원소
31
을 찾음
- R은 왼쪽으로 이동하면서 피봇 보다 작은 원소를 찾다가 못 찾은 채로 원소
31
에서 L과 만남
- L과 R이 만났으므로 피봇과 교환하는데 R의 원소가 피봇이므로 결국 제자리가 확정
5) 퀵 정렬 알고리즘
quickSort(a[], begin, end)
if (m < n) then {
p <- partition(a, begin, end);
quickSort(a[], begin, p-1);
quickSort(a[], p + 1, end);
}
end quickSort()
partition(a[], begin, end)
pivot <- (begin + end)/2;
L <- begin;
R <- end;
while (L < R) do {
while(a[L] < a[pivot] and L < R ) do L ++;
while(a[R] >=a[pivot] and L < R ) do R --;
if( L < R ) then { // L의 원소와 R의 원소 교환
temp <- a[L];
a[L] <- a[R];
a[R] <- temp;
}
}
temp <- a[pivot]; // R의 원소와 피봇 원소 교환
a[pivot] <- a[R];
a[R] <- temp;
return R;
end partition()
(1) 메모리 사용 공간
(2) 연산시간
(2-1) 최선의 경우
- 피봇에 의해서 원소들이 왼쪽 부분 집합과 오른쪽 부분 집합으로 정확히 n/2개씩 이등분 되는 경우가 반복되어
수행 단계의 수가 최소가 되는 경우
(2-2) 최악의 경우
- 피봇에 의해서 원소들을 분할하였을 때 1개와 n-1개로 한쪽으로 치우쳐 분할되는 경우가 반복되어 수행 단계 수가
최대로 되는 경우
(2-3) 평균 시간 복잡도 : O(n log2 n)
- 같은 시간 복잡도를 가지는 다른 정렬 방법에 비해서 자리 교환 횟수를 줄임으로써 더빨리 실행되어 실행 시간 성능이
좋은 정렬 방법
댓글남기기