알고리즘 이론 - 카운팅 정렬

Code_Alpacat·2022년 1월 23일
0

기초 알고리즘!

목록 보기
18/19

카운팅 정렬(Counting Sort)

  • 카운팅 정렬은 계수 정렬이라고도 한다.
  • 카운팅 정렬은 정수로 이루어진 리스트만 정렬이 가능하다. 리스트의 정수의 값을 인덱스로 활용하는 방법을 사용하기 때문이다.
  • 그러므로, 값이 인덱스가 되기 위해서는 리스트 안의 최대값을 알아야 그 크기에 맞는 새로운 리스트를 선언해 줄 수 있다.
  • 0~100점 사이인 학생들의 성적과 같이 중복되는 값이 발생하는 리스트의 정렬에 좋음. 만약 값 차이가 많이나서 값이 0 ~ 100000 사이인 배열이라면 공간을 많이 차지할 수 있다.

사실 이해하기 처음엔 매우 어려울 수 있다. 과정은 다음과 같다.

  1. 배열 안의 가장 큰 수만큼의 크기의 리스트 c를 생성 후 0을 전부 할당.
  2. 순서대로 초기 입력받은 리스트 arr에 있는 중복된 수의 개수만큼 arr의 값에 해당하는 인덱스에 할당.
    ex) arr[1] = 9 arr[10] = 9 였으면 9가 두 번 나왔으므로, c[9] = 2가 되는 것이다.
  3. 리스트 c 값들의 누적합을 저장해가며 구한다.
  4. arr와 같은 크기의 sorted_arr를 생성해 arr에서 순서대로 나온 값들이 c의 인덱스 값이 되고, c의 인덱스 안의 값 -1 은 새로운 sorted_arr의 인덱스가 된다. 그리고 중복된 값이 arr에 있을 수 있으니 호출된 c의 인덱스를 1씩 감소시켜 줘야만 중복 값도 출력이 된다.
#카운팅 정렬
def counting_sorted(arr, K): #arr는 배열, K는 arr에 들어갈 수 있는 숫자들의 최대값이다. K는 arr의 요소들 중에 가장 큰 값 이상이어야만 한다.
    c = [0] * K # arr안에 포함될 수 있는 최대값 크기의 리스트 c를 생성하고 0을 할당한다.
    sorted_arr = [0] * len(arr) # 정렬된 arr를 저장하기위한 sorted_arr 리스트 생성.
    
    for i in arr: 
        c[i] += 1 # arr안의 값에 해당하는 c리스트의 인덱스에 해당 값의 개수를 할당. [0, 1, 1, 1, 1, 2, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    
    for i in range(1,K): #[0, 1, 2, 3, 4, 6, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9,....9]
        c[i] += c[i-1] #K크기의 배열이므로 K-1까지 c배열의 누적합을 구한다. 0~ K-1까지의 리스트이므로 없는 값은 0이 할당되어있다.
   
    for i in range(len(arr)): #sorted_arr[2] = 3, sorted_arr[5] = 5, sorted_arr[0] = 1 ...
        sorted_arr[c[arr[i]]-1] = arr[i] #입력받은 리스트 arr의 값을 순서대로 c를 기준으로 sorted_arr에 재배치한다.
        c[arr[i]] -= 1 # c 배열의 값을 1씩 줄여줌. 안 줄여준다면 중복을 제거해서 중복된 수의 자리가 0으로 채워져 정렬됨.

    return sorted_arr
        
arr = [3, 5, 1, 2, 9, 6, 4, 7, 5, 1, 1, 1]
print(counting_sorted(arr, 20)) # 20이 arr에 들어갈 수 있는 최대값임.

*시간복잡도는 선형 시간으로 O(N+k)이다. k는 배열에 있는 수의 최대값을 의미한다.

*효율이 좋지만 정수나 정수로 표현되는 값들을 가져야만 쓸 수 있고, 리스트의 크기가 작은데 값들의 차이가 심한 경우에는 공간 효율이 안좋다.

profile
In the future, I'm never gonna regret, cuz I've been trying my best for every single moment.

0개의 댓글

관련 채용 정보