πŸ“‚ 자료ꡬ쑰/μ •λ ¬

μΉ΄μš΄νŒ… μ •λ ¬ (Counting Sort)

Amenable 2023. 4. 12. 01:01

1. κ°œλ… πŸ‘‘

  'κ³„μˆ˜ μ •λ ¬'이라고도 λΆˆλ¦¬λŠ” 'μΉ΄μš΄νŒ… μ •λ ¬(Counting Sort)'은 각 μ›μ†Œλ“€μ΄ λͺ‡ κ°œμ”© μžˆλŠ”μ§€ λ‚˜νƒ€λ‚΄λŠ” count배열을 ν™œμš©ν•˜λŠ” μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.

  각 μ›μ†Œμ˜ 값이 count λ°°μ—΄μ˜ μΈλ±μŠ€κ°€ λ˜λ―€λ‘œ 'μ •μˆ˜λ‚˜ μ •μˆ˜λ‘œ ν‘œν˜„ν•  수 μžˆλŠ” 자료'에 λŒ€ν•΄μ„œλ§Œ 적용 κ°€λŠ₯ν•˜λ‹€.

 

2. λ™μž‘λ°©μ‹ πŸŽ“

  λ™μž‘ 방식은 λ‹€μŒκ³Ό κ°™λ‹€.

  1. μ›μ†Œμ˜ μ΅œλŒ“값을 ν¬ν•¨ν•  μˆ˜ μžˆλŠ” λ°°μ—΄ μ„€μ •
  2. 각각의 μ›μ†Œκ°€ λͺ‡ λ²ˆ λ“±μž₯ν•˜λŠ”μ§€ μΉ΄μš΄νŒ…
    count λ°°μ—΄μ˜ μΈλ±μŠ€ = μ›μ†Œ κ°’
    count λ°°μ—΄μ˜ κ°’ = λ“±μž₯ 횟수
  3. count λ°°μ—΄μ„ λˆ„μ ν•©μœΌλ‘œ λ§Œλ“€μ–΄μ£ΌκΈ°
  4. μ •λ ¬λ˜μ§€ μ•Šμ€ λ°°μ—΄(μ΄ˆκΈ°κ°’)의 λ’€μ—μ„œλΆ€ν„° λŒλ©΄μ„œ, μ›μ†Œμ˜ κ°’κ³Ό λ™μΌν•œ μΈλ±μŠ€κ°€ κ°€λ¦¬ν‚€λŠ” κ³³μ— μ›μ†Œ λ°°μΉ˜ν•΄ μ£ΌκΈ°

  '0 2 1 1 4 4 4 3 5'κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ λ™μž‘λ°©μ‹μ„ μ•„λž˜μ˜ 그림을 ν†΅ν•˜μ—¬ 이해해 보자.

  λ™μž‘λ°©μ‹μ—μ„œ 2κ°€μ§€ 의문점이 생길 수 μžˆλ‹€.

  1. λ°°μ—΄μ˜ λ’€μ—μ„œλΆ€ν„° λŒλ©΄μ„œ 자리λ₯Ό λ°°μΉ˜ν•  λ•Œ count값을 κ°μ†Œμ‹œν‚€λŠ” μ΄μœ λŠ”?
      count값을 κ°μ†Œμ‹œμΌœμ•Όμ§€ λ‹€μŒμ— 같은 값이 듀어왔을 λ•Œ μ•Œλ§žμ€ μžλ¦¬μ— μ°Ύμ•„κ°ˆ 수 μžˆλ‹€. μœ„μ—μ„œ count[4]에 ν•΄λ‹Ήν•˜λŠ” κ°’을 κ³„μ†ν•΄μ„œ κ°μ†Œμ‹œμΌ°κΈ° λ•Œλ¬Έμ— '7, 6, 5'의 μΈλ±μŠ€μ— ν•΄λ‹Ήν•˜λŠ” μœ„μΉ˜μ— 4κ°€ λ°°μΉ˜λ  μˆ˜ μžˆμ—ˆλ‹€.
  2. λˆ„μ ν•©μ„ ν•΄μ€˜μ•Ό ν•˜λŠ” μ΄μœ λŠ”?
      λˆ„μ ν•©μ„ ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ—λŠ” count 배열을 λŒλ©΄μ„œ 'idx값을 idx에 ν•΄λ‹Ήν•˜λŠ” κ°’'만큼 λ°°μΉ˜ν•˜λ©΄ λœλ‹€. μœ„μ˜ μ˜ˆμ œμ—μ„œλŠ” '0을 1번, 1을 2번, 2λ₯Ό 1번, 3을 1번, 4λ₯Ό 3번, 5λ₯Ό 1번' λ°°μΉ˜ν•˜λ©΄, '0 1 1 2 3 4 4 4 5'λ₯Ό 얻을 수 μžˆλ‹€.
      ν•˜μ§€λ§Œ, μœ„μ˜ κ²½μš°μ™€ 달리 μ—°μ†λœ 값이 μ•„λ‹Œ '1 2023 0'을 μ •λ ¬ν•˜λŠ” 과정을 생각해 보자. 이런 경우 0λΆ€ν„° 2023κΉŒμ§€ countλ₯Ό λŒμ•„μ•Ό ν•œλ‹€.
      κ·ΈλŸ¬λ‚˜ λˆ„μ ν•©μ„ μ‚¬μš©ν•˜λ©΄ μœ„μ—μ„œ λ™μž‘ν–ˆλ˜ κ²ƒμ²˜λŸΌ μ›μ†Œμ˜ 개수인 N만큼만 count에 μ ‘κ·Όν•˜λ©΄ λœλ‹€. μ΄λŸ¬ν•œ 점으둜 인해 countλ₯Ό λˆ„μ ν•©ν•΄μ„œ μ‚¬μš©ν•œλ‹€.

 

3. κ΅¬ν˜„(JAVA) 🎩

public static void main(String[] args) {
    int arr[] = {0, 2, 1, 1, 4, 4, 4, 3, 5};
    int sorted_arr[] = new int[arr.length];

    int maxValue = 0;
    for(int i : arr) {
        maxValue = Math.max(maxValue, i);
    }
    // 1. μ›μ†Œμ˜ μ΅œλŒ“κ°’μ„ 포함할 수 μžˆλŠ” λ°°μ—΄ μ„€μ •
    int count[] = new int[maxValue + 1];

    // 2. 각각의 μ›μ†Œκ°€ λͺ‡ 번 λ“±μž₯ν•˜λŠ”μ§€ μΉ΄μš΄νŒ…
    for(int i = 0; i < arr.length; i++) {
        count[arr[i]]++;
    }

    // 3. count 배열을 λˆ„μ ν•©μœΌλ‘œ λ§Œλ“€κΈ°
    for(int i = 1; i < count.length; i++) {
        count[i] += count[i - 1];
    }

    // 4. λ’€μ—μ„œλΆ€ν„° 배열을 λŒλ©΄μ„œ μ›μ†Œμ˜ κ°’κ³Ό λ™μΌν•œ μΈλ±μŠ€κ°€ κ°€λ₯΄ν‚€λŠ” 곳에 μ›μ†Œ λ°°μΉ˜ν•΄μ£ΌκΈ°
    for(int i = arr.length - 1; i >= 0; i--) {
        count[arr[i]]--;
        sorted_arr[count[arr[i]]] = arr[i];
    }

    for(int i : sorted_arr) {
        System.out.print(i + " ");
    }
    // 0 1 1 2 3 4 4 4 5 
}

 

4. μ‹œκ°„λ³΅μž‘λ„ & κ³΅κ°„λ³΅μž‘λ„ πŸ‘’

μ‹œκ°„λ³΅μž‘λ„

  μ›μ†Œμ˜ 개수λ₯Ό N이라 ν•˜κ³  μ›μ†Œμ˜ μ΅œλŒ“κ°’μ„ K라고 ν•˜μž. λ™μž‘κ³Όμ •μ—μ„œμ˜ μ‹œκ°„λ³΅μž‘λ„λŠ” μ•„λž˜μ™€ κ°™λ‹€.

  • counting 배열을 λ§Œλ“€κΈ° → O(N)
  • counting 배열을 λˆ„μ ν•© μ‹œν‚€κΈ° → O(N + K)
  • λ’€μ—μ„œλΆ€ν„° 배열을 λŒλ©΄μ„œ, ν•΄λ‹Ήν•˜λŠ” 값을 μ΄μš©ν•˜μ—¬ μΈλ±μŠ€μ— μ›μ†Œ λ„£μ–΄μ£ΌκΈ° → O(N)

  κ·ΈλŸ¬λ―€λ‘œ μ‹œκ°„λ³΅μž‘λ„λŠ” O(N + K)이닀. ν•˜μ§€λ§Œ μΌλ°˜μ μœΌλ‘œλŠ” Kκ°€ 큰 값을 κ°€μ§€μ§€ μ•ŠμœΌλ―€λ‘œ 평균적인 μ‹œκ°„λ³΅μž‘λ„λŠ” O(N)이닀.

  μ΅œμ„ (BEST) 평균(AVERAGE) μ΅œμ•…(WORST)
μ‹œκ°„λ³΅μž‘λ„ O(N) O(N) O(N + K)

κ³΅κ°„λ³΅μž‘λ„

  K만큼 배열을 λ§Œλ“€μ–΄μ€˜μ•Ό ν•˜λ―€λ‘œ κ³΅κ°„λ³΅μž‘λ„λŠ” O(K)이닀.

 

5. μž₯점 & 단점 🧒

μž₯점

  • μ‹œκ°„λ³΅μž‘λ„(평균)κ°€ O(N)이닀. (일반적인 μƒν™©μ—μ„œ κ°€μž₯ λΉ λ₯Έ μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜μΈ ν€΅ μ •λ ¬μ˜ μ‹œκ°„λ³΅μž‘λ„ O(N logN)에 λΉ„ν•˜λ©΄ λ§€μš° λΉ λ₯Έ κ²ƒμ΄λ‹€.)

단점

  • 좔가적인 λ©”λͺ¨λ¦¬ κ³΅κ°„이 ν•„μš”ν•˜λ‹€.
  • 일뢀 κ°’(μ΅œλŒ“κ°’)에 μ˜ν•΄ λ©”λͺ¨λ¦¬μ˜ λ‚­λΉ„κ°€ μ‹¬ν•΄μ§ˆ μˆ˜ μžˆλ‹€.

 

ν•΄λ‹Ή 글은
Gyoogle λ‹˜μ˜ 'κ³„μˆ˜ μ •λ ¬(Counting Sort)',
멍멍멍 λ‹˜μ˜ 'Counting Sort : κ³„μˆ˜ μ •λ ¬',
Chappi λ‹˜μ˜ 'μ•Œκ³ λ¦¬μ¦˜ 6일차 - O(n) μ •λ ¬, κ³„μˆ˜ μ •λ ¬'
을 μ°Έκ³ ν•˜μ˜€μŠ΅λ‹ˆλ‹€.