Younngjun 2023. 2. 26. 10:49
셸 정렬

 

셸 정렬은 단순 삽입 정렬에서 특정 원소를 삽입할 위치가 멀리 떨어져 있으면 이동 횟수가 많아지는 단점을 보완한 정렬 알고리즘입니다. 비교하는 횟수를 확 줄인 알고리즘이죠.

 

배열 [8, 1, 4, 2, 7, 6, 3, 5]를 셸 정렬로 정렬하는 예시입니다. 먼저 서로 4칸씩 떨어진 원소를 꺼내어 (8, 7), (1, 6), (4, 3), (2, 5)의 4개의 그룹으로 나눈 후 각자 따로 정렬합니다. 그럼 다음과 같이 [7, 1, 3, 2, 8, 6, 4, 5]가 됩니다.(4-정렬)

 

다음은 2칸 떨어진 원소를 모두 꺼내 (7, 3, 8, 4), (1, 2, 6, 5) 두 그룹으로 나누고, 각각 정렬을 수행합니다.(2-정렬)

 

마지막으로 1칸 떨어진 배열, 즉 배열 전체에 단순 삽입 정렬을 적용하면 정렬이 완료됩니다.(1-정렬)

 

즉, 셸 정렬은 조금이라도 정렬이 된 상태에 가까운 배열로 만든 다음 마지막 삽입정렬을 하여 이동 횟수를 줄인 조금 더 효율적인 정렬을 하는 알고리즘입니다.

 

그럼 초기에 h-정렬을 하는 h 값을 어떻게 선택할까요? 일반적으로 h 값은 배열의 원소 수인 n을 9로 나누었을 때 그 몫을 넘지 않도록 설정해야 합니다. 또한 다음 수열을 사용했을 때 간단하고 효율적으로 정렬을 할 수 있습니다.

h = 1

while h < n//9:
    h = h * 3 + 1

 

다음은 셸 정렬 알고리즘 코드입니다.

def shell_sort(a: MutableSequence) -> None:
    n = len(a)
    h = 1

    while h < n // 9:
        h = h * 3 + 1

    while h > 0:
        for i in range(h, n):
            j = i - h
            tmp = a[i]
            while j >= 0 and a[j] > tmp:
                a[j + h] = a[j]
                j -= h
            a[j + h] = tmp
        h //= 3

 

셸 정렬의 시간 복잡도는 O(n^1.25)이고 단순 정렬의 시간 복잡도인 O(n^2)보다 매우 빠릅니다. 하지만 셸 정렬은 이웃하지 않고 떨어져 있는 원소를 서로 교환하므로 안정적이지 않습니다.

 

출처

 

Do it! 자료구조와 함께 배우는 알고리즘 입문 : 파이썬 편

https://velog.io/@roro/자료구조알고리즘-셸정렬