2. [CS] O(n log n) 정렬 - 퀵 정렬(Quick sort)

2025. 7. 25. 12:23·Computer Science/Algorithm

서론

이전에 IntroSort에 대한 설명글에서 퀵 정렬(Quick sort)에 대한 슈도코드와 간략한 설명을 다루었다. 이번 글에서는 퀵 정렬에 대한 구체적인 동작 방식과 효율성에 대해서 알아보도록 하자.

퀵 정렬(Quick sort)

퀵 정렬은 분할 정복(Divide and Conquer) 방식의 정렬 알고리즘이다. 기준이 되는 피벗(Pivot)을 하나 선택하고, 피벗보다 작은 값은 왼쪽, 큰 값은 오른쪽으로 분할해가며 정렬을 수행한다. 평균적으로 매우 빠르며($O(n log n)$), 제자리 정렬(추가적인 임시 배열을 사용하지 않음)이기 때문에 공간 효율성도 좋다.

Quick sort 과정 (namu wiki)

 

분할 정복

퀵 정렬은 앞서 설명했듯이 분할 정복을 사용해서 피벗을 기준으로 피벗보다 큰쪽, 피벗보다 작은쪽으로 배열을 분할하여 분할 정복이 진행된다.

log n (https://www.cs.cornell.edu/courses/cs3110/2011sp/Lectures/lec19-master/master.htm)

따라서 배열의 분할이 계속해서 $\frac{n}{2}$로 맞아떨어질 경우 같은 $O(n log n)$ 정렬 알고리즘중에서 월등한 시간복잡도를 가진다. (그래도 $O(n log n)$ 라는 한계가 있긴 함.)

피벗 선택

다만 퀵 정렬은 피벗의 선택 방법에 따라 시간 복잡도가 매우 떨어질 수 있다. 앞서 피벗을 선택하고 피벗을 기준으로 배열을 나눠 분할 정복을 시도한다고 했는데 만약 피벗으로 최댓값이나 최소값을 선택하고 그것이 반복된다면 시간복잡도가 $O(n^2)$으로 감소하게 된다.

최악의 경우

그러면 피벗을 무슨 기준으로 선택해야 할까? 여러 가지 기법들이 있는데 대표적인 게 피벗을 랜덤으로 선택(Random quick sort)하거나 N개의 원소를 골라서 중간값을 피벗으로 선택(Median of Three)하는 것으로 최악의 경우를 줄일 수 있다. 하지만 이 방법들을 사용하더라도 최악의 경우가 발생할 수 있기 때문에 퀵 정렬은 이전 글에서 설명한 인트로 소트등 하이브리드 정렬을 통해 $(O(nlogn)$의 시간복잡도를 보장하는 방식으로 주로 사용된다(C/C++, Unreal).

구현 예시

1. 피벗 선택

int pivot = arr[(i + j) / 2];
  • 구간의 중간 값을 피벗으로 선택
  • 성능 개선을 위해 다양한 방식이 가능 (예: median-of-three)

2. 양쪽 포인터 설정 및 분할

int i = left, j = right;
  • i: 왼쪽에서 오른쪽으로 스캔
  • j: 오른쪽에서 왼쪽으로 스캔
while (arr[i] < pivot) i++;
while (arr[j] > pivot) j--;
  • 왼쪽에서 피벗보다 크거나 같은 수
  • 오른쪽에서 피벗보다 작거나 같은 수를 찾는다

3. 값 교환 & 인덱스 갱신

if (i <= j) swap(arr[i++], arr[j--]);
  • i <= j일 때만 교환: 양쪽을 정확히 분할
  • 교환 후 각각 다음 인덱스로 이동

4. 재귀 호출 (Divide)

if (left < j) QuickSort(arr, left, j);
if (i < right) QuickSort(arr, i, right);
  • 왼쪽 구간과 오른쪽 구간으로 재귀적으로 다시 퀵 정렬 수행
  • 이 과정에서 점점 작은 문제로 나뉘고, 결국 정렬 완료됨

전체 코드

#include <bits/stdc++.h>
using namespace std;

void QuickSort(vector<int>& arr, int left, int right)
{
	int i = left, j = right;
	int pivot = arr[(i + j) / 2];

	do
	{
		while (arr[i] < pivot)i++;
		while (arr[j] > pivot)j--;

		if (i < j) swap(arr[i++], arr[j--]);
		else if (i == j) i++, j--;
	} while (i <= j);
	
	if (left < j) QuickSort(arr, left, j);
	if (i < right) QuickSort(arr, i, right);
}

int main()
{
	cin.tie(0)->sync_with_stdio(0);

	vector<int> arr = { 38, 27, 43, 3, 9, 82, 10 };
	QuickSort(arr, 0, arr.size() - 1);

	for (auto i : arr)cout << i << ' ';
}

'Computer Science > Algorithm' 카테고리의 다른 글

[CS] 다익스트라 알고리즘 (데이크스트라 알고리즘)  (4) 2025.08.01
1. [CS] O(n log n) 정렬 - 분할 정복과 합병 정렬(Merge sort)  (1) 2025.07.23
'Computer Science/Algorithm' 카테고리의 다른 글
  • [CS] 다익스트라 알고리즘 (데이크스트라 알고리즘)
  • 1. [CS] O(n log n) 정렬 - 분할 정복과 합병 정렬(Merge sort)
돼지표
돼지표
https://github.com/wkdgns135
  • 돼지표
    돼지표 개발 스토리
    돼지표
  • 전체
    오늘
    어제
    • 분류 전체보기 (106)
      • C++ (60)
        • Coding Test (53)
        • Study (1)
      • Python (1)
      • Machine Learning (2)
      • Computer Graphics (4)
        • Curly Hair Simulation (2)
      • GPU Programming (11)
        • CUDA basic (7)
        • CUDA fluidsGL (4)
      • Unreal 5 (21)
        • Troubleshooting (4)
        • FPS Shooting (5)
        • Study (10)
        • EOS (1)
      • Computer Science (7)
        • Algorithm (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    OpenGL
    UE5
    unreal 5
    구현
    수학
    위상 정렬
    CS
    Rendering Pipeline
    GPU Programming
    자료 구조
    C++
    BFS
    Fluid Simulation
    FPS
    Algorithm
    정렬
    dp
    그래프 탐색
    아이작 맵 생성
    CUDA
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
돼지표
2. [CS] O(n log n) 정렬 - 퀵 정렬(Quick sort)
상단으로

티스토리툴바