정렬 알고리즘은 다양한 아이디어를 포함하고 있습니다. 정렬만 하더라도 문제가 쉬워지는 경우가 있기에 꼭 알아야하는 알고리즘이기도 합니다.
정렬에 따른 장단점과 시간복잡도를 알아봅시다.
퀵 정렬과 머지 정렬은 따로 구현은 하지 않았습니다. 두 개는 이론을 중심으로 알아두는 것을 추천합니다.
아래 세 정렬은 시간복잡도가 \(O(N^2)\) 인 정렬입니다.
3-1. 선택정렬 (Selection Sort)
선택정렬의 핵심은 반복문 1번에 최솟값 또는 최댓값을 알 수 있다는 점입니다.
# lst : list, N : length
def selection_sort(lst, N):
for i in range(N):
min_idx = i
for j in range(i+1, N):
if lst[i] > lst[j] : min_idx = j
lst[i] = j
return lst
3-2. 버블정렬 (Bubble Sort)
버블정렬의 핵심은 이웃된 값을 비교하여 순서를 바꾸면 1회 순회마다 최솟값 또는 최댓값을 끝으로 보낼 수 있다는 점입니다.
# lst : list, N : length
def selection_sort(lst, N):
for i in range(N):
for j in range(i, N-1):
if lst[j] > lst[j+1] : lst[i], lst[j] = lst[j], lst[i]
return lst
3-3. 삽입 정렬 (Insertion Sort)
이 정렬은 이미 정렬된 부분 수열에서 자신의 위치를 찾아가는 방법을 사용합니다.
여기서부터는 시간복잡도가 \(O(nlogn)\)인 정렬 알고리즘 입니다.
3-3. 퀵 정렬 (Quick Sort)
퀵 정렬은 말그대로 빠른 정렬 방법입니다. 이 알고리즘의 핵심은 분할정복입니다.
- 기준점을 가지고 배열의 원소를 나누는 방법
3-4. 병합 정렬 (Merge Sort)
병합 정렬은 분할 정복을 바탕으로 한 정렬 방법입니다. 이 알고리즘의 핵심은 분할정복입니다.
- 정렬된 두 배열로 정렬된 배열을 만드는 방법 (merge)
재귀적으로 배열을 2개씩 나누고, 길이가 1인 배열부터 차근차근 merge하는 것이 핵심입니다.
def merge(l_lst, r_lst):
l_len, r_len = len(l_lst), len(r_lst)
ret, lp, rp = [], 0, 0
while lp < l_len and rp < r_len:
if l_lst[lp] <= r_lst[rp]:
ret.append(l_lst[lp])
lp += 1
else:
ret.append(r_lst[rp])
rp += 1
return ret + l_lst[lp:] + r_lst[rp:]
def merge_sort(lst):
if len(lst) == 1: return lst
size = len(lst)//2
l_lst, r_lst = lst[:size], lst[size:]
l_lst, r_lst = merge_sort(l_lst), merge_sort(r_lst)
return merge(l_lst, r_lst)
3-5. 힙 정렬 (Heap Sort)
앞서 공부한 Heap이라는 자료구조를 활용하면 쉽게 정렬할 수 있습니다. Heap은 최소 또는 최대 값을 항상 꺼내올 수 있습니다.
그렇다면 모든 원소를 Heap에 넣고, 하나씩 빼면 자동으로 정렬되지 않을까요?
from heapq import *
def heapsort(lst):
heapify(lst)
return [heappop(lst) for i in range(len(lst))]
3-6. 기수 정렬 (Radix Sort)
알고리즘에서는 종종 메모리와 시간의 trade-off가 있습니다.
def radix_sort(lst, N):
MN, MX = min(lst), max(lst)
sorted_lst = [0 for _ in range(MX-MN+1)]
for val in range(lst):
sorted_lst[val-MN] += 1
ret = [] # sorted array
for idx, val in enumerate(range(MX-MN+1)):
if val > 0 :
for _ in range(val) : ret.append(idx)
return ret