220318_TIL
업데이트:
퀵 정렬
퀵 정렬이란 기준점 (pivot)을 정하여 기준점보다 작은 데이터는 왼쪽 , 큰 데이터는 오른쪽으로 모으는 것을 반복하여 정렬하는 정렬 방식이다. 함수는 왼쪽 + 기준점 + 오른쪽 리스트를 합쳐서 리턴한다.
- 알고리즘 구현
- 리스트 갯수가 한개이면 해당 리스트를 리턴함
- 리스트 갯수가 한개 이상이면 리스트의 맨 앞의 데이터를 기준점(pivot)으로 놓기
- left와 right 리스트 변수를 만든다
- 맨 앞의 데이터를 뺀 나머지 데이터를 기준점과 비교하고 피봇보다 작으면 left.append , 피봇보다 크면 right.append
- return 값은 함수(left) + pivot + 함수(right)로 재귀 호출
import random
def qsort(data):
if len(data) <= 1 :
return data
left, right = list(), list()
pivot = data[0]
for index in range(1, len(data)):
if pivot > data[index]:
left.append(data[index])
else:
right.append(data[index])
return qsort(left) + [pivot] + qsort(right)
data_list = random.sample(range(100),10)
qsort(data_list)
100까지의 수 중에서 10개를 랜덤하게 뽑아 정렬되었다.
더 간결한 코드는 list comprehension을 사용하면 된다.
def qsort(data):
if len(data) <= 1:
return data
pivot = data[0]
left = [ item for item in data[1:] if pivot > item ]
right = [ item for item in data[1:] if pivot <= item ]
return qsort(left) + [pivot] + qsort(right)
이 알고리즘의 시간복잡도는 O(n log n) 이다.
병합 정렬
병합 정렬은 재귀용법을 활용한 정렬 알고리즘으로 리스트가 있을 때 절반으로 잘라 비슷한 크기의 두 부분 리스트로 나누고 각 부분 리스트를 재귀함수를 이용해 합병 정렬을 하는 알고리즘이다. 그래서 split 하는 함수와 merge하는 함수 두개가 필요하다.
-
mergesplit 함수
리스트 갯수가 한개이면 값 리턴하고 그렇지 않으면 리스트를 두개로 나눈다.
left = mergesplit(앞), right = mergesplit(뒤)
return merge(left, right)
-
merge 함수
sorted라는 리스트 변수를 하나 만들고 left_index와 right_index를 0으로 둔다.
왼쪽 리스트와 오른쪽 리스트를 비교하면서 작은 값들을 sorted에 저장하고 해당 인덱스를 1씩 증가시킨다. 끝까지 순회하면 정렬이 끝난다.
- 최종 코드
import random
def merge(left, right):
merged = list()
left_point, right_point = 0, 0
# case1 - left/right 둘다 있을때
while len(left) > left_point and len(right) > right_point:
if left[left_point] > right[right_point]:
merged.append(right[right_point])
right_point += 1
else:
merged.append(left[left_point])
left_point += 1
# case2 - left 데이터가 없을 때
while len(left) > left_point:
merged.append(left[left_point])
left_point += 1
# case3 - right 데이터가 없을 때
while len(right) > right_point:
merged.append(right[right_point])
right_point += 1
return merged
def mergesplit(data):
if len(data) <= 1:
return data
medium = int(len(data) / 2)
left = mergesplit(data[:medium])
right = mergesplit(data[medium:])
return merge(left, right)
data_list = random.sample(range(100), 10)
mergesplit(data_list)
병합 정렬 알고리즘의 시간 복잡도는 O(n log n)이다.
백준 알고리즘 - 수 정렬하기2
병합 정렬을 이용하여 푸는 문제였다. 오늘 배운 병합정렬이 실제 문제에서 어떻게 활용되는지 배웠다. 핵심은 left와 right로 리스트를 slicing하고 각 리스트의 인덱스를 0으로 놓아 비교한 후에 인덱스 값을 증가시키면서 정렬하는 것이었다. 그런데 실제 코테에서는 파이썬 라이브러리에 있는 sorted() 이용하면 7줄이면 끝나더라 ㅎㅎ
댓글남기기