퀵 정렬(Quick sort)

상위문서 : 자료구조

필수참고문서 : 정렬 기법


목차

1. 개요
2. 퀵셀렉션
3. 구현
3.1. JAVA로 구현
3.2. C#으로 구현


1.개요

일반적으로 많이 쓰이는 정렬이 퀵정렬인데 퀵정렬은 적절한 원소 하나를 기준(이것을 피벗이라고 한다)으로 삼아 그보다 작은 것을 앞으로 보내고 그 뒤로가 또 다른 피벗을 기준 삼아 작은 것, 큰것으로 나눈뒤 나누어진 각각에서 다시 피벗을 잡고 정렬해서 각각의 크기가 0이나 1이 될 때까지 정렬한다. 원래는 정렬 기법쪽에 같이 서술할려고 했는데 내용이 길어져서 따로 문서를 만들었다.

예를들어 5,6,4,7,3,8,2,9,1을 퀵정렬하면 다음과 같이 볼 수 있다.
5,6,4,7,3,8,2,9,1 에서 무난하게 5를 피벗으로 잡자 사실 피벗은 전체 원소 값중 중간값을 잡는것이 가장 좋다.
이제 피벗을 기준으로 큰 숫자를 남은 원소들 첫번째에서 부터 탐색해  만약 찾았으면 이제는 남은 원소들 집합에서 끝자리로 가 찾은 원소와 비교해서 작으면 서로의 위치를 바꾼다. 여기서 피벗을 기준으로 큰 숫자를 찾는 인덱스는 i라고 하며 찾은 숫자에 의하여 뒤에서 부터 작은 숫자를 찾는 인덱스는 j라고 하겠다.

5  (넘을 수 없는 벽)  6,4,7,3,8,2,9,1
                           i               j

6과 피벗(5)을 비교했더니 6이 더 크다 그래서 끝자리로 가보니 j 인덱스에 1이 있다. 피벗과 1을 비교했더니 1이 더 작으므로 둘의 위치를 바꾼다. 또한 i 인덱스는 1 증가시키며 j인덱스는 -1을 해준다.

5  (넘을 수 없는 벽)  1,4,7,3,8,2,9,6
                             i          j

이제 4와 피벗을 비교했더니 4가 더 작다 i 인덱스 1을 증가해보자


5  (넘을 수 없는 벽)  1,4,7,3,8,2,9,6
                               i        j
7과 피벗을 비교했더니 7이 더크다. 뒤 부분으로 가서 j인덱스의 숫자를 보니 9이다. 피벗보다 9는 더 크니 j인덱스의 값을 -1 한다.


5  (넘을 수 없는 벽)  1,4,7,3,8,2,9,6
                               i      j
이번엔 피벗과과 2를 비교했더니 피벗이 더 크다. 따라서 7과 2의 자리를 바꿔준다. 또한 i 인덱스는 1 증가시키며 j인덱스는 -1을 해준다.

5  (넘을 수 없는 벽)  1,4,2,3,8,7,9,6
                                  i j
이제 3과 피벗을 비교했더니 피벗이 더 크므로 i를 1증가해준다.

5  (넘을 수 없는 벽)  1,4,2,3,8,7,9,6
                                   (ij)
이제 8과 피벗을 비교했더니 8이 더 크므로 j와 비교해준다. 근대 둘다 똑같다. 이럴땐 j를 -1해준다.

5  (넘을 수 없는 벽)  1,4,2,3,8,7,9,6
                                  j i
이제 피벗과 3을 비교했더니 3이 더 작으므로 둘의 위치를 바꿔줘야하는데 i와 j가 교차했다.  이럴땐 피벗을 j 위치에 넣어준다.

3,1,4,2,[5],8,7,9,6
이제 5를 기준으로 왼쪽으로는 5보다 작은 값 오른쪽으로는 큰값들만 모였다. 이제 다시 3과 8을 피벗으로 삼아 위 알고리즘을 다시 해주자
참고로 왼쪽 피벗을 기준으로 이제 맨끝은 2가 된다. 5는 이제 고정이다.
3(넘을 수 없는 벽) 1,4,2 [5] 8(넘을 수 없는 벽)7,9,6

솔직히 너무 하기 귀찮다. 아무튼 위의 방법대로 하면 정렬이 된다.
필자는 종이에 적어서 풀었는데 위에서 오른쪽은 한번만 정렬해주면 더 이상 안해줘도 되지만 왼쪽은 2번인가 해야한다.

2.퀵셀렉트

그런데 위에서 보았듯이 피벗이 만약에 1이라면 퀵소트의 시간 복잡도는 원래 평균적으로 O(n logn)을 보이지만  최악의 경우 O(n^2)이 될 수 있다. 그리고 처음 선택된 피벗이 1일 경우 O(n^2)에 근접할 확률이 매우 크다. 따라서 퀵소트의 성능을 평균적인 O(n logn)으로 보장하려면 적절한 피벗을 선택해주는 방법이 필요하다. 퀵셀렉트는 n개의 원소들중 k번째 숫자를 알고 싶을때 사용하는 방법이다.
방법은 다음과 같다.
 파티션에서 랜덤으로 피벗을 뽑는다. 그 후 리스트를 피벗보다 작은 것은 왼쪽 큰 것은 오른쪽으로 정렬하고 피벗 인덱스를 반환한다. 

3. 구현

3.1.JAVA로 구현

3.2.C#으로 구현

on 2017년 6월 11일 일요일 | A comment?
0 responses to “퀵 정렬(Quick sort)”

Leave a Reply

최근 많이 본 글