Sort

정렬이란 물건을 크기 순으로 오름차순이나 내림차순으로 나열한 것이다.

  • 단순하지만 비효율적 : 삽입, 선택, 버블 정렬

  • 복잡하지만 효율적 : 퀵, 히프, 합병, 기수 정렬

선택정렬(selection sort)

가장 작은 데이터를 선택해 맨 앞에 있는 데이터와 바꾸고, 그 다음 작은 데이터를 선택해 앞에서 두 번째 데이터와 바꾸는 과정을 반복하는 방법

  1. 주어진 리스트 중에 최솟값을 찾는다.

  2. 그 값을 맨 앞에 위치한 값과 교체한다(패스(pass)).

  3. 맨 처음 위치를 뺀 나머지 리스트를 같은 방법으로 교체한다.

비교하는 것이 상수 시간에 이루어진다는 가정 아래, n개의 주어진 리스트를 이와 같은 방법으로 정렬하는 데에는 O(n^2) 만큼의 시간이 걸린다. 이는 정렬해야하는 데이터 개수가 100배 늘어나면 이론적으로 수행시간은 10,000배 늘어나는 것이다.

삽입정렬(insertion sort)

자료 배열의 모든 요소를 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여, 자신의 위치를 찾아 삽입함으로써 정렬을 완성하는 알고리즘이다.

삽입 정렬은 필요할 때만 위치를 바꾸므로 데이터가 거의 정렬되어 있을 때 훨씬 효율적이다.

  • 복잡도

    • 최선의 경우(이미 정렬) : O(n)

    • 최악의 경우(역순으로 정렬된 경우) : O(n^2)

보통 삽입 정렬이 퀵 정렬보다 비효율 적이나, 이미 정렬되어있는 경우에는 퀵정렬보다 더 강력하다. 따라서 거의 정렬되어 있는 상태라면, 삽입 정렬을 이용하는 것이 더 좋다.

버블정렬(bubble sort)

인점한 2개의 레코드를 비교하여 순서대로 되어 있지 않으면 서로 교환한다.

  • 복잡도(최상, 평균, 최악) : O(n^2)

합병 정렬(merge_sort)

  1. 리스트를 두 개의 균등한 크기로 분할하고 분할된 부분리시트를 정렬한다.

  2. 정렬된 두개의 부분 리스트를 합하여 전체 리스트를 정렬한다.

  • 복잡도 : O(n*log(n))

기수정렬(Radix Sort)

기수 정렬은 정수의 자리수를 기준으로 낮은 자리수부터 비교해 정렬하는 알고리즘입니다.

예를 들어 3자리 수라면 1의자리, 10의자리 , 100의 자리 숫자를 순서대로 비교해서 정렬하는 방법입니다.

  • 복잡도 : O(dn) d는 자릿수

퀵정렬(Quick sort)

  1. pivot(기준값) 정하기

  2. pivot보다 작은 원소들은 왼쪽, 큰 원소는 오른쪽

  3. pivot을 기준으로 왼쪽 배열과 오른쪽 배열을 새로운 배열로 정하고 각 배열구간에서 1번과정 재귀적 반복

  4. 일반적으로 처음 또는 마지막 원소를 pivot으로 잡는다.

  • 시간 복잡도

    • 평균적 : O(nlog(n))

    • 최악의 경우 : O(N^2)

데이터 수
N^2(선택정렬, 삽입 정렬)
NlogN(퀵 정렬)

1,000

약 1,000,000

약 10,000

1,000,000

약 1,000,000,000,000

약 20,000,000

다만 퀵정렬은 평균적으로 시간복잡도가 O(NlogN)이지만 최악의 경우(이미 정렬되어 있는 경우) O(N^2)인 것을 주의해야한다.

정렬(heap sort)

  1. n개의 노드에 대한 완전이진트리를 구성한다. 이때 루트 노드부터 부노드, 왼쪽 자노드, 오른쪽 자노드 순으로 구성한다.

  2. 최대 힙을 구성한다.

  3. 한번에 하나씩 요소를 힙에서 삭제하면서 저장한다.

힙 정렬이 최대로 유용한 경우는 전체 자료가 아닌 가장 큰 값 몇개만 필요할 때이다.

구현

  • 힙구현은 힙(heap)에서 확인할 수 있다.

  • 복잡도

    • 힙 삭제 시간 O(logn)*n = O(nlogn)

계수 정렬(Count Sort)

계수 정렬은 특정한 조건이 부합할 때만 사용할 수 있지만 매우 빠른 정렬 알고리즘이다.

모든 데이터가 양의 정수인 상황을 가정해볼 것이다. 데이터의 개수가 N, 데이터 중 최대값이 K일 때, 계수 정렬은 최악의 경우에도 수행시간 O(N+K)를 보장한다.

계수 정렬은 데이터의 크기 범위가 제한되어 정수 형태로 표현할 수 있을 때만 사용할 수 있다. 만약 데이터의 값이 무한한 범위를 가질 수 있는 실수형 데이터가 주어지는 경우에는 계수 정렬은 사용하기 어렵다. 일반적으로 가장 큰 데이터와 가장 작은 데이터의 차이가 1,000,000을 넘지 않을 때 효과적으로 사용할 수 있다.

정렬 (12) - 계수 정렬 (Counting Sort)

계수 정렬은 위와 모든 범위를 담을 수 있는 크기의 리스트를 선언해야하기 때문에, 크기에 제한이 있다.

  • 시간 복잡도 : O(N+K), 최대값 크기 K, 데이터수 N

파이썬 3.7 정렬 알고리즘 비교

데이터 수(N)
선택 정렬
퀵 정렬
기본 정렬 라이브러리

100

0.0123

0.00156

0.00000753

1000

0.354

0.00343

0.0000365

10000

15.475

0.0312

0.000248

선택 정렬은 기본 정렬 라이브러리를 포함해 다른 알고리즘과 비교했을 때 매우 비효율 적이지만, 특정한 리스트에서 가장 작은 데이터를 찾을때는 유용하게 사용된다.

sorted()

파이썬 기본 정렬 라이브러리에서 제공하는 sorted()는 퀵정렬 과 동작 방식이 비슷한 병합 정렬을 기반(병합 정렬 + 삽입정렬)으로 만들어졌다. 병합 정렬은 퀵정렬보다 일반적으로 느리지만, 최악의 경우에도 O(NlogN) 시간 복잡도를 보장한다.

리스트, 딕셔너리 자료형을 받아서 정렬된 결과를 출력한다.

정렬시에 Key 매개변수를 입력받아 정렬할 수 있는데, key값으로는 정렬 기준의 하나의 함수가 입력된다.

sort()

리스트 변수가 하나 있을 때 내부 원소를 바로 정렬할 수도 있다. sort() 를 이용하면 별도의 정렬된 리스트가 반환되지 않고 내부 원소가 바로 정렬된다.

정렬 라이브러리는 항상 최악의 경우에도 시간복잡도 O(NlogN)을 보장한다.

Last updated

Was this helpful?