복잡하거나 큰 문제를 여러개로 나눠서 푸는 방법.
작은문제로 나누어 해결한 뒤 합치는 과정을 거친다.
분할이 가능한지, 분할정복 알고리즘을 이용하는 것이 효율적일지를 생각해보고 사용해야 한다.
분할정복을 이용한 정렬 방법 중 피벗(pivot)과 파티션(partition)을 이용해 분할한 뒤 정렬하는 방법.
실제 사용빈도가 높은 알고리즘 중 하나로 버블, 삽입, 선택정렬보다 효율적이다.
def quick_sort(lst):
if len(lst) <= 1: # 재귀를 통해 리스트 원소가 1개가 되면 그대로 해당값 반환
return lst
else:
pivot = lst[0] # 피벗을 0번 인덱스로 지정
greater = [i for i in lst if i > pivot] # 피벗보다 큰 경우 greater 변수에 리스트로 넣는다.
smaller = [i for i in lst if i < pivot] # 피벗보다 작은 경우 smaller 변수에 리스트로 넣는다.
return quick_sort(smaller) +[pivot] + quick_sort(greater) # 재귀함수를 통하 작은것부터 결과 리스트를 합쳐낸다.
lst = [4,7,1,6,3,2,9,0,8,5]
quick_sort(lst)
[output]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
합병정렬 또는 머지소트라고도 불리며, 이역시도 분할정복을 이용한 정렬방법이기에 큰 문제를 작은 문제로 나눈 뒤에 이를 해결하여 병합하는 방식을 취한다.
def merge_sort(lst):
a = len(lst) # 리스트의 길이
mid = a //2 # 중간값
if a >1: # 길이가 1인 경우는 그대로 반환한다.
L = lst[:mid] # 중간점 기준 left
R = lst[mid:] # 중간점 기준 right
merge_sort(L) # 분할이 될때까지 계속해서 재귀호출로 분할을 진행한다.
merge_sort(R)
i = j = k = 0 # 분할이 완료된 후 작업진행
while i < len(L) and j < len(R): # L과 R의 각각의 원소들을 반복 비교해 정렬해나가면서 병합한다.
if L[i] > R[j]: # L의 i번쨰 원소가 R의 j번째 원소보다 클 경우
lst[k] = R[j] # lst의 k번째 원소를 R의 j번째에 있던 가장 작은 원소로 맞춰놓는다.
j += 1 # j번째는 리스트에 넣었으니 그다음 원소와 비교를 위해 j에 1을 더해 반복문 진행
elif L[i] < R[j]: # 위와 반대로 진행
lst[k] = L[i]
i += 1
k += 1 # 반복 1회마다 메인 리스트에 원소를 넣었으니 그 다음 원소에 넣을 수 있도록 1을 더해줌
while i < len(L): # 연산 진행 후, L 또는 R이 불균형해 한쪽 리스트가 남아있을 때,
lst[k] = L[i] # 해당 리스트 원소들은 이미 반대편 리스트보다 큰 값이므로 반복문으로 넣어준다.
i +=1
k += 1
while j < len(R): # L과 마찬가지
lst[k] = R[j]
j +=1
k += 1