Sort Algorithm

JeongChaeJin·2022년 10월 6일
0
  • 데이터를 특정 기준에 따라 순서대로 나열하는 것
  • 문제 상황에 따라 적절한 정렬 알고리즘이 공식처럼 사용된다.

선택 정렬

  • 처리되지 않은 데이터 중 가장 작은 데이터를 선택해 맨 앞에 있는 데이터와 바꾸는 것을 반복
    • 선형 탐색 2중 반복문

array = [7, 5, 9 ...]

for i range(len(array)):
	min_index = i
    for j in range(i + 1, len(array)):
    	if array[min_index] > array[j]:
        	min_index = j
	array[i], array[min_index] = array[min_index], array[i]
    
print(array)
  • N번 만큼 가장 작은 수를 찾아 맨 앞으로 보내야 한다.
  • N + N-1 + N-2 + ... + 2
    • (N^2 + N - 2) / 2 => O(N^2)

삽입 정렬

  • 처리되지 않은 데이터를 하나씩 골라 적절한 위치에 삽입
  • 구현 난이도가 높지만 일반적으로 선택 정렬보다 빠르다.
array = [7, 5, 9 ...]

for i in range(1, len(array)):
	for j in range(i, 0, -1):
    	if array[j] < array[j-1]:
        	array[j], array[j-1] = array[j-1], array[j]
        else:
        	break

print(array)
  • O(N^2)
  • 현재 리스트의 데이터가 거의 정렬되어 있는 상태라면 매우 빠르게 동작
    • 최선의 경우 O(N)
      • 모두 정렬되어있다고 하면, 바로 else로 걸려서 break 되버림

퀵 정렬

  • 기준 데이터를 설정하고 그 기준보다 큰 데이터와 작은 데이터의 위치를 바꾸는 방법
    • 피벗을 기준으로 데이터 묶음을 나누는 작업을 Partition이라고 한다.
    • 피벗을 기준으로 나뉘므로 점점 연산이 줄어든다.
  • 이상적인 경우 Partition이 절반씩일어나는데, 전체 연산횟수로 N x logN(너비 x 높이) = O(NlogN)을 기대할 수 있게 된다. (평균)
  • 최악의 경우 O(N^2) 시간 복잡도를 갖는다.
    • 첫 번쨰 원소를 피벗으로 할 때, 이미 정렬된 배열에 대해 퀵정렬 수행 시 발생
array = [5, 7, 9, 0 ... ]

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
		whlie (right >= start and array[right] > array[pivot])
        	right += 1
            
		if (left > right):
        	array[right], array[pivot] = array[pivot], array[right]
        else:
        	array[right], array[left] = array[left], array[right]
            
	quick_sort(array, start, right - 1)
    quick_sort(array, right + 1, end)
    
quick_sort(array, 0, len(array) - 1)
print(array)

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)
  • python 장점을 살린 방식

계수정렬

  • 특정 조건이 부합할 떄만 사용할 수 있지만 매우 빠르게 동작하는 정렬 알고리즘
    • 데이터 크기 범위가 제한되어 정수 형태로 표현할 수 있을 때 사용 가능
  • Data 개수 N, 양수 Data 중 최대 값이 K 일 때 최악의 경우에도 O(N+K) 보장
  • 인덱스가 Data를 의미하고 그 값이 개수를 의미한다.
    • 해당 데이터가 몇번 등장했는지를 저장 후 차례대로 등장한 만큼 반복하며 출력
array = [7 ,5 ,9 , ...]

count = [0] * (max(array) + 1)

for i in range(len(array)):
	count[array[i]] += 1
    
for i in range(len(count)):
	for j in range(count[i]):
    	print(i, end=' ')
  • 시간, 공간 복잡도 모두 O(N+K)
    • Data 0, 999999로 단 두개만 존재하는 경우 공간 비효율성을 초래할 수 있다.
  • 동일한 값을 가지는 데이터가 여러개 등장할 때 효과적으로 사용할 수 있다.
    • 데이터 정렬 범위가 한정적이면서 중복 데이터가 여러번 등장

두 배열의 원소 교체

  • 매번 배열 A에서 가장 작은 원소를 골라 배열 B에서 가장 큰 원소와 교체
  • 두 배열의 원소가 최대 10만개가 입력될 수 있다는 점을 감안하면 최악의 경우 O(NlogN)을 보장하는 정렬 알고리즘을 사용해야함을 알 수 있다.
a.sort()
b.sort(reverse=True)

for i in range(k):
	if a[i] < b[i]:
    	a[i], b[i] = b[i], a[i]
	else:
    	break

print(sum(a))
profile
OnePunchLotto

0개의 댓글