랜덤 방식: N 개 중 임의의 위치
중값 위치 (Middle Index)방식: 배열의 중간 위치 → length(arr)/2
중간 값 (Median)방식: 앞, 뒤, 중간 위치 중 중간 크기의 값이 있는 위치 사용
# 퀵 정렬 1 (5주 1차 수업)
def quick_sort1(a):
n=len(a)
if n<=1:
return a # 재귀 종료 조건
pivot=a[-1] # 편의상 리스트의 마지막 값을 기준 값으로 정함
g1=[]
g2=[]
# 파티셔닝: pivot을 기준으로 큰수와 작은 수를 좌우로 나눔 (partition)
# -> pivot의 위치 return
for i in range(n-1): # 마지막 값은 기준 값이므로 제외
# 기준 값과 비교
if a[i] <pivot:
g1.append(a[i])
else:
g2.append(a[i])
return quick_sort1(g1)+[pivot]+quick_sort1(g2)
d=[6, 8, 3, 9, 10, 1, 2, 4, 7, 5]
print(quick_sort1(d)) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 출처: YouTube 알고리즘 강의
array1=[5, 7, 9, 0, 3, 1, 6, 2, 4, 8]
def quick_sort(array, start, end):
# 원소가 1개인 경우 종료
if start>=end: return
pivot=start # pivot은 첫번째 원소
left=start+1 # pivot보다 큰 데이터 담는 index
right=end # pivot보다 작은 데이터 담는 index
while(left<=right):
# pivot보다 큰 데이터를 찾을 때까지 반복
# (pivot보다 작으면 left index를 바꾸면서)
while(left<=end and array[left]<=array[pivot]):
left+=1
# pivot보다 작은 데이터를 찾을 때까지 반복
# (pivot보다 크면 right index를 바꾸면서)
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(array1, 0, len(array1)-1)
# 오름차순 정렬된 것 확인 가능
print(array1) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
분할 정복 방식으로 설계된 알고리즘으로 큰 문제를 반으로 쪼개서 문제 해결
분할 과정
합병 과정
array = [8,4,6,2,9,1,3,7,5]
# 분할 과정
def merge_sort(array):
if len(array) < 2: # 배열 길이가 1 이하일 경우 종료
return array
mid = len(array) // 2
low_arr = merge_sort(array[:mid])
high_arr = merge_sort(array[mid:])
merged_arr = [] # 작은 수 저장하는 배열
l = h = 0
while l < len(low_arr) and h < len(high_arr):
if low_arr[l] < high_arr[h]:
merged_arr.append(low_arr[l])
l += 1
else:
merged_arr.append(high_arr[h])
h += 1
merged_arr += low_arr[l:]
merged_arr += high_arr[h:]
return merged_arr
array = merge_sort(array)
최대 힙 트리나 최소 힙 트리를 구성해 정렬을 하는 방법
힙 순서 속성을 만족하는 완전 이진 트리
Min Heap (최소힙)
Max Heap (최대힙)
import heapq
# 계산복잡도: O(n*log(N))
# 이 부분 다시 확인 필요
# best case: O(N)... 정확하게 순서대로 위치해 있을 때 sort가 실제로 1번도 진행 X
def heap_sort(nums):
heap=[]
for num in nums:
heapq.heappush(heap, num)
sorted_nums=[]
while heap:
sorted_nums.append(heapq.heappop(heap))
return sorted_nums
print(heap_sort([6, 8, 3, 9, 10, 1, 2, 4, 7, 5]))
import heapq # 최소 힙
heap=[]
# 숫자를 삽입
heapq.heappush(heap, 4)
heapq.heappush(heap, 1)
heapq.heappush(heap, 7)
heapq.heappush(heap, 3)
# 최소 힙으로 트리구조 배열 출력
print(heap) # [1, 3, 7, 4]
print(heapq.heappop(heap)) # 1
print(heap) # [3, 7, 4]
print(heapq.heappop(heap)) # 3
print(heapq.heappop(heap)) # 7
print(heap[0]) # 4
"""
heapq.heapify: 기존의 리스트를 힙으로 만드는 함수
"""
heap2=[4, 1, 7, 3, 8, 5]
heapq.heapify(heap2)
print(heap2) # [1, 3, 5, 4, 8, 7]
특정한 조건이 부합할 때문 매우 빠르다.
데이터의 크기 범위가 제한되어 정수 형태로 표현 가능할 때만 사용 가능하다.
일반적으로 "(가장 큰 데이터) - (가장 작은 데이터) <1,000,000" 일 때 효과적으로 사용 가능