컬렉션의 원소를 어떤 순서(크기, 사전순, 날짜…)로 다시 배치하는 알고리즘. 같은 일을 하는 방법이 여럿이고 각자 강점이 달라, 트레이드오프를 익히기 좋은 주제다.
기본 세 가지 (평균 O(n²), 추가 공간 O(1))
- 버블 정렬(Bubble Sort): 이웃한 둘을 비교해 큰 값을 뒤로 보낸다. 한 바퀴 동안 교환이 없으면 멈추게 하면 거의 정렬된 입력에서 빠르다
- 선택 정렬(Selection Sort): 남은 것 중 최솟값을 찾아 앞으로 보낸다. 교환 횟수가 적다
- 삽입 정렬(Insertion Sort): 앞쪽을 정렬된 상태로 유지하며 다음 원소를 알맞은 자리에 끼운다. 거의 정렬된 데이터와 작은 배열에 강해서, 실제 언어의 정렬 구현도 작은 구간에는 이것을 쓴다
더 빠른 정렬 (O(n log n))
- 병합 정렬: 항상
O(n log n)이고 안정적이지만 추가 메모리가 든다 - 퀵 정렬: 평균적으로 가장 빠른 편이지만 최악은
O(n²) - 비교 기반 정렬(Comparison Sort)은 최악·평균의 경우
O(n log n)보다 빠를 수 없다(거의 정렬된 입력처럼 유리한 경우는 예외)
기수 정렬
기수 정렬(Radix Sort)은 비교하지 않고 숫자의 자릿수별로 버킷에 나눴다 모으기를 반복한다. O(n·k)(k는 자릿수)로, 자릿수가 작은 정수 정렬에 빠르다.
JavaScript의 sort
[10, 9, 1].sort()는 [1, 10, 9]다. 기본이 문자열 비교이기 때문이다. 숫자는 비교 함수를 넘긴다: arr.sort((a, b) => a - b). 원본을 바꾸므로 복사본이 필요하면 toSorted()를 쓴다. 엔진의 sort는 안정 정렬(Stable Sort)이 보장된다(ES2019부터).