다양한 정렬 알고리즘에 대한 정리 글을 들어가기에 앞서 왜(WHY) 정렬 알고리즘에 대해 알아야 하는지 나의 생각을 정리해본다면 다음과 같다.
앞으로 다양한 종류, 크기, 형태의 데이터를 다루게 될 것 이고, 이러한 데이터 중 나에게 필요한, 필요에 맞는 데이터를 잘 추출하기 위해서는 데이터를 정렬하는 과정이 필수적이기 때문에 정렬 알고리즘에 대해 공부해야한다.
a = [3,8,5,35,21,41,25]
def BubbleSort(a, N): # a는 정렬할 리스트, N은 원소의 수, 리스트만 입력받고 len(list)를 사용해도 무방함
for i in range(N-1, 0 , -1):
for j in range(i):
if a[j] > a[j+1]:
a[j], a[j+1] = a[j+1], a[j]
장점👍 : 인접한 값만 계속해서 비교하는 방식으로 구현이 쉬우며, 코드가 직관적이다. n개 원소에 대해 n개의 메모리를 사용하기에 데이터를 하나씩 정밀 비교가 가능하다.
단점👎 : 최선, 평균, 최악의 경우 모두 O(n^2)이라는 시간복잡도를 가진다. n개 원소에 대해 n개의 메모리를 사용하기에 원소의 개수가 많아지면 비교 횟수가 많아져 성능이 저하된다.
항목들의 순서를 결정하기 위해 집합에 각 항목이 몇 개씩 있는지 세는 작업을 통해 선형 시간에 정렬하는 알고리즘
카운팅 정렬의 제한사항
def Counting_Sort(a):
m = max(a) # 주어진 리스트 a의 정수 최대값 찾기
Counting_list = [0]*(m+1) # 최대값 +1만큼 카운팅 리스트를 생성
for i in range(len(a)):
Counting_list[a[i]] += 1
print(Counting_list)
for x in range(1,m+1):
Counting_list[x] += Counting_list[x-1]
#카운팅 리스트 완성
print(Counting_list)
result = [0]*len(a)
for r in range(len(a)-1, -1, -1): # 리스트의 마지막 값부터 역순으로 순회
Counting_list[a[r]] -= 1
result[Counting_list[a[r]]] = a[r]
print(result)
li = [4,4,3,2,1,5,6,7]
Counting_Sort(li)
애니매이션으로 보면 이해하기 쉽다.
링크로 접속해보는 것을 권장한다.
장점👍 : 비교적 준수한 시간복잡도를 갖는다. k의 수가 작을경우 O(N)에 가까운 시간 복잡도를 갖는다. 또한 안정정렬을 구현할 수 있다. 위 코드 처럼 카운팅 정렬을 구현할 경우 리스트에서 중복되는 값들 끼리도 그 순서가 보장된다.(4가 두번 나오는데 4끼리의 순서가 변하지 않음)
단점👎 : 정수 최대값만큼 counting_list를 만들어야 하므로 메모리의 낭비가 발생 될 수 있다.
def SelectionSort(li):
for i in range(len(li)-1):# -1번까지 하는 이유는 n-1번 정렬을 수행하면 최댓값이 마지막 인덱스 자리에 위치하게 되기 때문이다.
min_index = i
for z in range(i,len(li)):
if li[min_index] > li[z]:
min_index = z
li[i],li[min_index] = li[min_index],li[i]
return li