정렬 알고리즘 개요
- 정렬Sorting이란 데이터를 특정한 기준에 따라서 순서대로 나열하는 것
선택정렬
- 가장 작은 데이터를 선택해 맨 앞에 있는 데이터와 바꾸고, 그 다음 작은 데이터를 선택해 앞에서 두 번째 데이터와 바꾸는 과정을 반복
- 매번 가장 작은 데이터를 선택한다는 의미에서 선택정렬Selection Sort 알고리즘이라고 함
array = [7,5,9,0,3,1,6,2,4,8]
for i in range(len(array)):
min_index = i
for j in range(i+1, len(array)):
if array[j] < array[min_index]:
min_index = j
array[i], array[min_index] = array[min_index], array[i]
print(array)
삽입정렬
- 데이터를 하나씩 확인하며, 각 데이터를 적절한 위치에 삽입하는 것
- 구현 난이도 : 삽입정렬 > 선택정렬
- 시간 효율성 : 삽입정렬 > 선택정렬
- 선택정렬은 무조건 모든 원소를 비교하고 위치를 바꿈
- 삽입정렬은 필요할 때만 위치를 바꾸므로 데이터가 거의 정렬되어 있을 때 효율적
- 특정한 데이터를 적절한 위치에 삽입한다고 하여 삽입정렬Insertion Sort라고 함
- 삽입정렬은 특정한 데이터가 적절한 위치에 들어가기 이전에, 그 앞까지의 데이터는 이미 정렬되어 있다고 가정
array = [7,5,9,0,3,1,6,2,4,8]
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)
퀵 정렬
- 기준 데이터를 설정하고 그 기준보다 큰 데이터와 작은 데이터의 위치를 바꾸는 것
- 퀵 정렬에서는 피벗pivot이 사용
- 큰 숫자와 작은 숫자를 교환할 때, 교환하기 위한 '기준'을 바로 '피벗'이라 함
- 퀵 정렬을 수행하기 전에는 피벗을 어떻게 설정할 것인지 미리 명시해야 함
- 피벗을 설정하고 리스트를 분할하는 방법에 따라서 여러가지 방식으로 퀵 정렬을 구분
- 해당 내용에선 '호어분할'방식을 기준으로
- '호어분할'방식 : 리스트에서 첫 번째 데이터를 피벗으로 정함
- 퀵 정렬을 3개의 파트로 살펴보자
1. 리스트의 첫 번째 데이터를 피벗으로 설정 -> 왼쪽(피벗 다음 원소)에서부터 피벗보다 큰 데이터를 선택 -> 오른쪽(리스트 제일 마지막 원소)에서부터 피벗보다 작은 데이터를 선택 -> 두 데이터의 위치를 변경
2. 왼쪽에서 찾는 값과 오른쪽에서 찾는 값의 위치가 엇갈린 경우 -> 작은 데이터와 피벗의 위치를 변경
3. 1번과 2번의 과정을 완료한 후, 피벗의 왼쪽에는 피벗보다 작은 데이터가 위치, 피벗의 오른쪽에는 피벗보다 큰 데이터가 위치함
- '재귀함수'와 동작원리가 같음
- 따라서, 종료조건도 있어야 함. 퀵 정렬의 종료조건은 현재 리스트의 데이터 개수가 1인 경우
array = [5,7,9,0,3,1,6,2,4,8]
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)
print(quick_sort(array))
계수정렬
- 계수정렬Count Sort알고리즘은 특정한 조건이 부합할 때만 사용할 수 있지만 매우 빠른 정렬 알고리즘
- 특정조건 : '데이터의 크기 범위가 제한되어 정수 형태로 표현할 수 있을 때'
- ex) 0이상 100이하 성적 데이터, 가장 큰 데이터와 가장 작은 데이터의 차이가 1,000,000을 넘지 않을 때
- 이러한 특징을 가지는 이유는, 계수정렬은 모든 범위를 담을 수 있는 크기의 리스트(배열)를 선언해야하기 때문
- 주어진 리스트가 "7 5 9 0 3 1 6 2 9 1 4 8 0 5 2"라고 할 때,
- 먼저 가장 큰 데이터와 가장 작은 데이터의 범위가 모두 담길 수 있도록 하나의 리스트를 생성
- 현재 예시에서는 가장 큰 데이터가 '9', 가장 작은 데이터가 '0'
- 따라서 정렬할 데이터의 범위는 0부터 9까지이므로 리스트의 인덱스가 모든 범위를 포함할 수 있도록 크기가 10인(0~9) 리스트를 선언
- 그 다음 데이터를 하나씩 확인하며 데이터의 값과 동일한 인덱스의 데이터를 1씩 증가시킴
array = [7,5,9,0,3,1,6,2,9,1,4,8,0,5,2]
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=' ')
파이썬의 정렬 라이브러리
- sorted() : 변환되는 결과는 리스트 자료형
array = [7,5,9,0,3,1,6,2,4,8]
result = sorted(array)
print(result)
- sort() : 별도의 정렬된 리스트가 반환되지 않고 내부 원소가 바로 정렬
array = [7,5,9,0,3,1,6,2,4,8]
array.sort()
print(array)
- key 매개변수를 입력으로 받을 수 있음
- key 값으로는 하나의 함수가 들어가야 하며 이는 정렬 기준이 됨
array = [('바나나', 2), ('사과', 5), ('당근', 3)]
def setting(data):
return data[1]
result = sorted(array, key = setting)
print(result)