카운팅 정렬

항목들의 순서를 결정하기 위해 집합에 각 항목이 몇 개씩 있는지 세는 작업을 하여, 선형 시간에 정렬하는 효율적인 알고리즘

 

 

제한 사항

  • 정수나 정수로 표현할 수 있는 자료에 대해서만 적용 가능
  • 카운트들을 위한 충분한 공간을 할당하려면 집합 내의 가장 큰 정수를 알아야 한다.
  • 시간 복잡도는 O(n + k): n은 리스트 길이, k는 정수의 최대값

 

1단계

data에서 각 항목들의 발생 회수를 세고, 정수 항목들로 직접 인덱스 되는 카운트 배열 counts에 저장한다.

data가 [0, 4, 1, 3, 1, 2, 4, 1] 이라면

counts는 [1, 3, 1, 1, 2] 가 된다.

이 뜻은 counts의 각 인덱스 번호가 data에 있는 정수가 된다.

즉, 위의 counts에서 0은 1개, 1은 3개, 2는 1개.. 이런 식으로 표현이 된 것이다.

 

2단계

정렬된 집합에서 각 항목의 앞에 위치할 항목의 개수를 반영하기 위해 counts의 원소를 조정한다.

for문을 돌려 count의 1번 인덱스 부터 전의 인덱스 값을 더해 준다.

counts = [1, 3, 1, 1, 2]에서

counts = [1, 4, 5, 6, 8]이 된다.

 

3단계

이제 2단계를 지난 counts를 활용해 data를 정렬한다.

data의 마지막 부터 회문을 돌려 그 값을 인덱스로 표현한 counts에 1을 빼주고,

counts의 그 인덱스에 있는 숫자를 인덱스로 하여 data에 넣어준다.

글로 표현 하면 설명이 어렵기 때문에 직접 보자

 

이런 식으로 정렬이 된다.

그럼 이 과정을 코드로 표현해 보자

nums = list(map(int, input().split()))  # 원래의 data
N = len(nums)
arr = [0]*N                  # 정렬된 값을 넣을 list
c = [0] * (max(nums) + 1)    # counts에 넣을 list

for num in nums:             # 1단계
    c[num] += 1
for i in range(1, len(c)):   # 2단계
    c[i] += c[i-1]
for i in range(len(arr)-1, -1, -1):  # 3단계
    c[nums[i]] -= 1
    arr[c[nums[i]]] = nums[i]

print(*arr)

 

카운팅 정렬의 평균, 최악 수행시간은 O(n+k)이고, n이 기뵤적 작을때만 가능하다는 단점이 있다.

'알고리즘 개념' 카테고리의 다른 글

Stack 스택 (파이썬)  (0) 2022.09.01
트리 순회 코드 (파이썬)  (0) 2022.08.28
2차원 리스트 지그재그 순회 (파이썬)  (0) 2022.08.21
투 포인터 (파이썬)  (0) 2022.08.06
WHO AM I ?  (0) 2022.07.25
복사했습니다!