자료구조

[파이썬 자료구조] 퀵정렬

j9m 2020. 6. 10. 23:55
728x90
반응형

정렬 중에서  퀵정렬에 대해서 알아보겠습니다. 2가지의 방식이 있습니다.

방법1.

L은 피벗보다 작은 집단, G는 피벗보다 큰 집단

1단계. 입력된 임의의 원소를 피벗으로 선택합니다. 피벗은 기준이 되는 원소입니다.

2단계. 피벗을 기준으로 작은 원소들, 피벗과 같은 원소들, 피벗보다 큰 원소들로 나눕니다.

3단계. 재귀적으로 정렬하고 크기순으로 놓으면 끝

파이썬으로 간단히 구현해보면

1
2
3
4
5
6
7
8
def quick_sort(S):
    if len(S) < 2:
        return S
    pivot = random.choice(S)
    L = [x for x in S if x < pivot]
    E = [x for x in S if x == pivot]
    G = [x for x in S if x > pivot]
    return quick_sort(L) + E + quick_sort(G)
cs

먼저 리스트 S에서 랜덤으로 피벗을 구합니다. import random을 하셔야합니다.

L, E, G 집단으로 원소들을 나눠줍니다.

8번째 줄에서 다시 집단들을 재귀적으로 나눠줍니다. 결과적으로 정렬된 리스트를 얻을 수 있습니다.

방법2.

2번째 방식은 새로운 리스트에 합치는것이 아니라 리스트 내에서 피벗을 정해서 정렬하는 방법입니다.

1단계. 랜덤으로 피벗을 정하고  맨 왼쪽에 있는 인덱스와 맨 오른쪽에 있는 인덱스를 선택

2단계. j가 i보다 작고 피벗보다 작으면 교환이 이루어집니다. 이과정을 재귀적으로 반복합니다.

3단계:  i가 j보다 크거나 같아지면 가운데에 피벗을 넣어주면 끝

파이썬으로 구현해보면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def quick_sort(S, a, b):
    if a >= b:
        return
    pivot_idx = random.randint(a, b)
    S[pivot_idx], S[a] = S[a], S[pivot_idx]
    pivot = S[a]
    left = a+1
    right = b
    while left <= right:
        while left <= right and S[left] < pivot:
            left += 1
        while left <= right and pivot < S[right]:
            right -= 1
        if left <= right:
            S[left], S[right] = S[right], S[left]
            left, right = left + 1, right - 1
    S[right], S[a] = S[a], S[right]
    quick_sort(S, a, right - 1)
    quick_sort(S, right + 1, b)
cs

S는 리스트이고 a와b는 각각 리스트의 양쪽 index입니다.

랜덤인트로 피벗을 정하고 피벗을  맨왼쪽으로 보내줍니다.

그리고 위에서 설명한 방식으로 진행됩니다.

퀵정렬의 수행시간

최선의 경우는 랜덤으로 뽑은 피벗이 항상 중간값을 갖는 경우입니다.

수행시간 T(n) = 2*T(n/2) + cn 

위에서 설명한 것처럼 리스트를 두개로 나누기 때문에 2*T(2/n)이 나온거고 cn은 피벗과 비교하는 시간입니다.

계속 2개씩 나눠지기 때문에 최대 log(n)번 나눌 수 있습니다. (이진트리)

따라서 k= log(n) 이므로 O(nlogn)의 수행시간을 가집니다.

최악의 경우는 피벗을 뽑을때마다 최솟값이나 최대값인 경우입니다.

한 쪽으로 기울어진 트리가 만들어지게 됩니다. 따라서 n(n+1)/2 -> O(n^2)의 수행시간이 걸립니다.

따라서 Big-O 표기법으로 시간복잡도는 O(n^2)입니다.

 

 

 

 

728x90
반응형