💻코딩테스트
[이코테_코딩테스트] 정렬 알고리즘 - 퀵 정렬 (Quick Sort)
퀵 정렬 (Quick Sort)
- 기준 데이터(Pivot)를 설정하고 그 기준보다 큰 데이터와 작은 데이터의 위치를 바꾸는 방법
- 일반적인 상황에서 가장 많이 사용되는 정렬 알고리즘 중 하나
- 병합 정렬(Merge Sort)와 더불어 대부분의 프로그래밍 언어의 정렬 라이브러리의 근간이 되는 알고리즘
- 가장 기본적인 퀵 정렬은 첫 번째 데이터를 기준 데이터(Pivot)로 설정한다.
퀵 정렬 동작 예시
[Step 0] 현재 피벗의 값은 ‘5’, 왼쪽에서부터 ‘5’보다 큰 데이터를 선택하므로 ‘7’ 선택, 오른쪽에서부터 ‘5’보다 작은 데이터를 선택하므로 ‘4’ 선택 → 두 데이터의 위치 변경
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fc5641f05-45f6-4817-8132-91985861d7e5%2FUntitled.png?table=block&id=73bb3b79-4080-4ed9-8c84-eb997f6f48b5&cache=v2)
[Step 1] 현재 피벗의 값은 ‘5’, 왼쪽에서부터 ‘5’보다 큰 데이터를 선택하므로 ‘9’ 선택, 오른쪽에서부터 ‘5’보다 작은 데이터를 선택하므로 ‘2’ 선택 → 두 데이터의 위치 변경
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fecb162f2-45f3-475f-96ae-d6d4cad19fc4%2FUntitled.png?table=block&id=40a7bfef-09b7-435e-895c-af8a9f50fd06&cache=v2)
[Step 2] 현재 피벗의 값은 ‘5’, 왼쪽에서부터 ‘5’보다 큰 데이터를 선택하므로 ‘6’ 선택, 오른쪽에서부터 ‘5’보다 작은 데이터를 선택하므로 ‘1’ 선택
- 아래 사진처럼 위치(화살표)가 엇갈리는 경우 피벗(Pivot)과 ‘작은 데이터’의 위치 변경
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F92fe6c34-fcc0-4abd-99ba-60ff8819e981%2FUntitled.png?table=block&id=a9eed757-fe5f-4172-bd7a-4743b975e919&cache=v2)
[분할 완료] ‘5’ 기준으로 왼쪽 데이터는 모두 ‘5’보다 작고, 오른쪽에 있는 데이터는 모두 ‘5’보다 크다.
- 이렇게 피벗(Pivot)을 기준으로 데이터 묶음을 나누는 작업을 분할(Divide)라고 한다.
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F0217b221-3a57-47ad-af36-c14341d36a80%2FUntitled.png?table=block&id=fe8ae73f-e7fd-4964-8ba5-8c8d342d56f3&cache=v2)
[왼쪽 데이터 묶음 정렬] 왼쪽에 있는 데이터에 대해 위 과정처럼 정렬 수행
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fd26a32cc-2991-4984-afbd-d96d7e27599f%2FUntitled.png?table=block&id=a019787f-4fe5-469a-811c-961b37e36780&cache=v2)
[오른쪽 데이터 묶음 정렬] 오른쪽에 있는 데이터에 대해 위 과정처럼 정렬 수행
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F920ba089-d5a2-49d5-900c-34533a616cbc%2FUntitled.png?table=block&id=d3e6e34f-65ee-4b70-a961-180cb7cd9c71&cache=v2)
퀵 정렬이 빠른 이유 - 직관적인 이해
- 이상적인 경우 분할이 절반씩 일어난다면 전체 연산 횟수로 기대할 수 있음
- 너비 X 높이 =
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F27a71597-b703-42d1-a349-8feb9e1c6567%2FUntitled.png?table=block&id=e8ee50f8-a80a-4b38-a3b0-7f8abdac0e9c&cache=v2)
퀵 정렬의 시간 복잡도
- 퀵 정렬은 평균의 경우 의 시간 복잡도를 가진다.
- 최악의 경우 의 시간 복잡도를 가진다.
- ‘0’보다 큰 데이터 선택 ‘1’, 작은 데이터 선택할 때 ‘1’과 교차
- ‘0’ 자기 자신의 위치와 변경 후 분할
- 왼쪽 데이터 묶음 정렬은 없고, 오른쪽 데이터 묶음 정렬은 ‘1’부터 ‘9’까지
- 위 과정 반복
첫 번째 원소를 피벗으로 삼을 때, 이미 정렬된 배열이라면?
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fdd3859e1-7521-41e7-ac34-296ffc86c185%2FUntitled.png?table=block&id=d692f42d-5187-42ca-a5aa-93296e62addc&cache=v2)
퀵 정렬 소스코드 - 일반적인 방식 (Python)
array = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8] def quick_sort(array, start, end): if start >= end: # 원소가 한 개인 경우 return pivot = start left = start + 1 right = end while(left <= right): while(left <= end and array[left] <= array[pivot]): # 피벗보다 큰 값 찾기 left += 1 while(right > start and array[right] >= array[pivot]): # 피벗보다 작은 값 찾기 right -= 1 if left > right: # 위치 엇갈린 경우 -> 피벗과 피벗보다 작은 값의 위치 변경 array[right], array[pivot] = array[pivot], array[right] else: # 위치 안엇갈린 경우 -> 피벗보다 작은 값, 피벗보다 큰 값 위치 변경 array[left], array[right] = array[right], array[left] # 분할 이후 왼쪽 묶음과 오른쪽 묶음 각각 정렬 quick_sort(array, start, right - 1) quick_sort(array, right + 1, end) quick_sort(array, 0, len(array) - 1) print(array)
퀵 정렬 소스코드 - 파이썬의 장점을 살린 방식
- 리스트 슬라이싱 + 리스트 컴프리헨션 사용
array = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8] def quick_sort(array): if len(array) <= 1: return array pivot = array[0] tail = array[1:] left_side = [x for x in tail if x <= pivot] # 분할된 왼쪽 묶음 right_side = [x for x in tail if x > pivot] # 분할된 오른쪽 묶음 return quick_sort(left_side) + [pivot] + quick_sort(right_side) print(quick_sort(array))
이 글은 유튜브 “동빈나” 채널의 “(이코테 2021 강의 몰아보기) 4. 정렬 알고리즘” 영상을 보고 작성하였습니다.