- 데이터를 특정 기준에 따라 순서대로 나열하는 것
- 문제 상황에 따라 적절한 정렬 알고리즘이 공식처럼 사용된다.
선택 정렬
- 처리되지 않은 데이터 중 가장 작은 데이터를 선택해 맨 앞에 있는 데이터와 바꾸는 것을 반복
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)
계수정렬
- 특정 조건이 부합할 떄만 사용할 수 있지만 매우 빠르게 동작하는 정렬 알고리즘
- 데이터 크기 범위가 제한되어 정수 형태로 표현할 수 있을 때 사용 가능
- 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))