OPEN HYPER STEP
← 목록으로 (math)
MATH · 28 / 45
math
CHAPTER 28 / 45
읽기 약 2
FUNCTION

정렬의 수학: 왜 O(n log n)이 한계인가


핵심 개념

버블 O(n²) vs 퀵/머지 O(n log n) — 비교 정렬 하한 + 카운팅 정렬 O(n).

본문

정렬 알고리즘 비교

알고리즘시간 (평균)공간안정인플레이스
버블O(n²)O(1)
선택O(n²)O(1)
삽입O(n²)O(1)
머지O(n log n)O(n)
O(n log n)O(log n)
O(n log n)O(1)
카운팅O(n+k)O(k)
라딕스O(d×n)O(n+k)
Python TimsortO(n log n)O(n)

버블 정렬 — O(n²)

PYTHON📋 코드 (15줄)
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False
        for j in range(n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                swapped = True
        if not swapped:
            break  # 이미 정렬됨
    return arr


print(bubble_sort([5, 3, 1, 4, 2]))  # [1, 2, 3, 4, 5]
# 비교 횟수: n + (n-1) + ... + 1 = n(n+1)/2 ≈ n²/2

머지 정렬 — O(n log n)

PYTHON📋 코드 (30줄)
def merge_sort(arr):
    if len(arr) <= 1:
        return arr

    mid = len(arr) // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])
    return merge(left, right)


def merge(left, right):
    result = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i]); i += 1
        else:
            result.append(right[j]); j += 1
    result.extend(left[i:])
    result.extend(right[j:])
    return result


print(merge_sort([5, 3, 1, 4, 2]))


# 분석:
# 분할: log n 단계 (절반씩)
# 각 단계 머지: O(n)
# 총: O(n log n)

퀵 정렬 — O(n log n) 평균

PYTHON📋 코드 (19줄)
def quick_sort(arr):
    if len(arr) <= 1:
        return arr

    pivot = arr[len(arr) // 2]
    left  = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]

    return quick_sort(left) + middle + quick_sort(right)


print(quick_sort([5, 3, 1, 4, 2]))


# 분석:
# 균등 분할 시: O(n log n)
# 최악(이미 정렬, 끝 피벗): O(n²)
# 무작위 피벗으로 최악 회피

비교 정렬의 하한 O(n log n) 증명

📋 코드 (8줄)
n개 원소의 가능한 순열: n!
각 비교는 1비트 (둘 중 어느 게 큰가) 정보 제공

n!개 결과를 구분하려면 log₂(n!)개 비교 필요
log₂(n!) ≈ n log n - 1.44n (스털링 근사)

→ 비교 정렬은 O(n log n)이 이론적 하한
→ 머지/퀵/힙 정렬이 점근적으로 최적

카운팅 정렬 — O(n) 가능 (조건부)

PYTHON📋 코드 (21줄)
def counting_sort(arr, max_val):
    """비교 없이 정렬 — O(n + k)"""
    count = [0] * (max_val + 1)
    for x in arr:
        count[x] += 1

    result = []
    for i, c in enumerate(count):
        result.extend([i] * c)
    return result


# 학생 점수 (0~100)
scores = [85, 90, 75, 60, 95, 80, 90, 75]
print(counting_sort(scores, 100))
# [60, 75, 75, 80, 85, 90, 90, 95]


# 조건:
# - 입력값이 정수 (또는 정수로 매핑 가능)
# - 값의 범위 k가 합리적 (k가 너무 크면 메모리 폭주)

Python의 Timsort

PYTHON📋 코드 (27줄)
# Python sorted() / list.sort()는 Timsort
# 머지 + 삽입 정렬 하이브리드
# 부분 정렬된 데이터에 매우 강함

import random
import time

# 무작위 데이터 — O(n log n)
arr1 = random.sample(range(1_000_000), 100_000)
t0 = time.perf_counter()
sorted(arr1)
print(f"무작위: {(time.perf_counter() - t0)*1000:.0f}ms")


# 거의 정렬됨 — O(n)에 가까움 (Timsort의 강점)
arr2 = list(range(100_000))
random.shuffle(arr2[-100:])  # 끝 100개만 셔플
t0 = time.perf_counter()
sorted(arr2)
print(f"거의 정렬: {(time.perf_counter() - t0)*1000:.0f}ms")


# 이미 정렬됨 — O(n)
arr3 = list(range(100_000))
t0 = time.perf_counter()
sorted(arr3)
print(f"이미 정렬: {(time.perf_counter() - t0)*1000:.0f}ms")

안정 정렬 (Stable Sort)

PYTHON📋 코드 (22줄)
# 같은 키의 원본 순서 보존

students = [
    ('Alice',   90),
    ('Bob',     85),
    ('Charlie', 90),  # Alice와 같은 점수
    ('Dave',    85),  # Bob과 같은 점수
]

# 점수로 정렬 — 안정적이면 같은 점수는 원본 순서
sorted_stable = sorted(students, key=lambda x: x[1], reverse=True)
print(sorted_stable)
# [('Alice', 90), ('Charlie', 90), ('Bob', 85), ('Dave', 85)]
# Alice > Charlie 순서 유지 (원본대로)


# 다중 키 정렬 — 안정 정렬 활용
# "이름 → 점수" 우선순위
sorted_multi = sorted(
    sorted(students, key=lambda x: x[0]),  # 1차: 이름
    key=lambda x: x[1], reverse=True       # 2차: 점수 (안정)
)

다음 챕터

CH.29 "검색의 수학" — 선형 vs 이진 + DB 인덱스가 빠른 이유.


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 데이터 정렬 코드를 분석해서
적합한 알고리즘과 안정성 요구사항을
검토해줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

한국 코딩 테스트 정렬 문제 Top 10과
각각 적합한 알고리즘 + 함정을
정리해줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 DB의 ORDER BY 쿼리들을 분석해서
인덱스 + 정렬 최적화 가능한 위치와
예상 성능을 보고해줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 빅데이터 정렬에서 분산 처리
(Spark/Hadoop)와 메모리 정렬 트렌드를
솔직히 알려줘.

⭐ 이것만 기억하세요
정렬의 수학: 왜 O(n log n)이 한계인가 이 3가지만 확실히 잡으세요
1.비교 정렬의 이론적 하한은 O(n log n) — 머지/퀵/힙이 점근적으로 최적
2.카운팅 정렬은 O(n) 가능하지만 정수+제한된 범위만 — 일반 비교 정렬은 못함
3.다음 챕터 CH.29에서 검색 — 정렬된 데이터의 이진 탐색 O(log n)


공유하기
진행도 28 / 45