λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Python/κ°œλ… 정리

🐍[파이썬] Hash, Hash Map, Hash Set

by eugene663 2025. 3. 20.

1. ν•΄μ‹œ(Hash)λž€?

ν•΄μ‹œλŠ” 데이터λ₯Ό λΉ λ₯΄κ²Œ 검색할 수 μžˆλ„λ‘ νŠΉμ • 값을 κ³ μœ ν•œ μ •μˆ˜κ°’(ν•΄μ‹œκ°’)으둜 λ³€ν™˜ν•˜λŠ” κ³Όμ •μž„. 이 과정은 일방ν–₯ ν•¨μˆ˜λ‘œ, μž…λ ₯값을 ν•΄μ‹œκ°’μœΌλ‘œ λ³€ν™˜ν•˜μ§€λ§Œ ν•΄μ‹œκ°’μ—μ„œ μž…λ ₯값을 볡원할 수 μ—†μŒ.

2. ν•΄μ‹œλ§΅(Hash Map)

  • ν•΄μ‹œλ§΅μ€ ν‚€(key)와 κ°’(value)의 쌍으둜 데이터λ₯Ό μ €μž₯ν•˜λŠ” 자료 κ΅¬μ‘°μž„.
  • νŒŒμ΄μ¬μ—μ„œλŠ” λ”•μ…”λ„ˆλ¦¬(Dictionary) κ°€ ν•΄μ‹œλ§΅μ— 해당함. ν‚€λŠ” ν•΄μ‹œκ°’μœΌλ‘œ λ³€ν™˜λ˜μ–΄ λΉ λ₯Έ μ‘°νšŒκ°€ κ°€λŠ₯함.

μ‚¬μš© 이유

  • λΉ λ₯Έ 쑰회: ν•΄μ‹œλ§΅μ€ ν‰κ· μ μœΌλ‘œ O(1)의 μ‹œκ°„ λ³΅μž‘λ„λ‘œ 데이터λ₯Ό μ‘°νšŒν•  수 있음.
  • 쀑볡을 ν—ˆμš©ν•˜μ§€ μ•ŠμŒ: ν‚€κ°€ μ€‘λ³΅λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μœ μΌν•œ 데이터λ₯Ό μ €μž₯ν•  수 있음.
  • νš¨μœ¨μ„±: 데이터λ₯Ό μ €μž₯ν•˜κ³  κ΄€λ¦¬ν•˜λŠ”λ° 맀우 νš¨μœ¨μ μž„.

κ΄€λ ¨ ν•¨μˆ˜ 및 λ©”μ„œλ“œ

  • dict.get(key, default=None): 킀에 ν•΄λ‹Ήν•˜λŠ” 값을 λ°˜ν™˜. ν‚€κ°€ μ—†μœΌλ©΄ default 값을 λ°˜ν™˜.
  • dict[key]: 킀에 ν•΄λ‹Ήν•˜λŠ” 값을 λ°˜ν™˜. ν‚€κ°€ μ—†μœΌλ©΄ KeyError λ°œμƒ.
  • dict.update(other_dict): λ‹€λ₯Έ λ”•μ…”λ„ˆλ¦¬μ˜ ν•­λͺ©μ„ ν˜„μž¬ λ”•μ…”λ„ˆλ¦¬μ— 좔가함.
  • dict.items(): λ”•μ…”λ„ˆλ¦¬μ˜ λͺ¨λ“  (key, value) μŒμ„ λ°˜ν™˜ν•¨.
  • dict.keys(): λ”•μ…”λ„ˆλ¦¬μ˜ λͺ¨λ“  ν‚€λ₯Ό λ°˜ν™˜ν•¨.
  • dict.values(): λ”•μ…”λ„ˆλ¦¬μ˜ λͺ¨λ“  값을 λ°˜ν™˜ν•¨.

3. ν•΄μ‹œμ…‹(Hash Set)

  • ν•΄μ‹œμ…‹μ€ μ€‘λ³΅λ˜μ§€ μ•ŠλŠ” 데이터λ₯Ό μ €μž₯ν•˜λŠ” 자료 ꡬ쑰둜, μ§‘ν•©(Set)의 νŠΉμ„±μ„ κ°–μŒ.
  • νŒŒμ΄μ¬μ—μ„œλŠ” set μžλ£Œν˜•μ΄ ν•΄μ‹œμ…‹μ— 해당함.

μ‚¬μš© 이유

  • 쀑볡 데이터 제거: ν•΄μ‹œμ…‹μ€ 쀑볡을 ν—ˆμš©ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— κ³ μœ ν•œ 데이터λ₯Ό μ €μž₯함.
  • λΉ λ₯Έ 검색: μ§‘ν•©μ˜ μ›μ†Œλ₯Ό O(1) μ‹œκ°„ λ³΅μž‘λ„λ‘œ 확인할 수 있음.

κ΄€λ ¨ ν•¨μˆ˜ 및 λ©”μ„œλ“œ

  • set.add(elem): μ›μ†Œλ₯Ό 셋에 좔가함.
  • set.remove(elem): μ…‹μ—μ„œ μ›μ†Œλ₯Ό μ œκ±°ν•¨. μ›μ†Œκ°€ μ—†μœΌλ©΄ KeyError λ°œμƒ.
  • set.discard(elem): μ›μ†Œλ₯Ό μ…‹μ—μ„œ μ œκ±°ν•¨. μ›μ†Œκ°€ 없어도 였λ₯˜ λ°œμƒν•˜μ§€ μ•ŠμŒ.
  • set.pop(): μ…‹μ—μ„œ μž„μ˜μ˜ μ›μ†Œλ₯Ό μ œκ±°ν•˜κ³  λ°˜ν™˜ν•¨.
  • set.union(other_set): 두 μ…‹μ˜ 합집합을 λ°˜ν™˜ν•¨.
  • set.intersection(other_set): 두 μ…‹μ˜ ꡐ집합을 λ°˜ν™˜ν•¨.
  • set.difference(other_set): 두 μ…‹μ˜ 차집합을 λ°˜ν™˜ν•¨.
  • set.symmetric_difference(other_set): 두 μ…‹μ˜ λŒ€μΉ­ 차집합을 λ°˜ν™˜ν•¨.

4. ν•΄μ‹œ 좩돌(Hash Collision)

ν•΄μ‹œ ν•¨μˆ˜λŠ” λ‹€μ–‘ν•œ μž…λ ₯값을 κ³ μœ ν•œ ν•΄μ‹œκ°’μœΌλ‘œ λ³€ν™˜ν•˜λ € ν•˜μ§€λ§Œ, κ²°κ΅­ ν•΄μ‹œκ°’μ΄ 쀑볡될 수 있음. 이λ₯Ό ν•΄μ‹œ 좩돌이라고 ν•˜λ©°, 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λ‹€μ–‘ν•œ 방법이 μ‚¬μš©λ¨.

  • 체이닝(Chaining): 좩돌이 λ°œμƒν•˜λ©΄ λ™μΌν•œ ν•΄μ‹œκ°’μ„ κ°€μ§„ ν•­λͺ©λ“€μ„ λ¦¬μŠ€νŠΈλ‚˜ λ§ν¬λ“œ 리슀트둜 μ—°κ²°ν•˜μ—¬ μ €μž₯함.
  • μ˜€ν”ˆ μ–΄λ“œλ ˆμ‹±(Open Addressing): 좩돌이 λ°œμƒν•˜λ©΄ λ‹€λ₯Έ 빈 자리λ₯Ό μ°Ύμ•„ 데이터λ₯Ό μ €μž₯함.

5. μ½”λ”©ν…ŒμŠ€νŠΈμ—μ„œμ˜ ν™œμš©

  • 쀑볡 μ›μ†Œ 확인: set을 μ΄μš©ν•΄ 쀑볡 μ›μ†Œλ₯Ό λΉ λ₯΄κ²Œ ν™•μΈν•˜κ³  μ œκ±°ν•  수 있음.
  • 두 리슀트의 ꡐ집합 κ΅¬ν•˜κΈ°: set의 intersection λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 두 리슀트의 κ³΅ν†΅λœ μ›μ†Œλ₯Ό λΉ λ₯΄κ²Œ ꡬ할 수 있음.
  • 단어 μΆœν˜„ 횟수 μ„ΈκΈ°: dictλ₯Ό μ΄μš©ν•˜μ—¬ 각 λ‹¨μ–΄μ˜ μΆœν˜„ 횟수λ₯Ό κ³„μ‚°ν•˜λŠ” 문제λ₯Ό ν’€ 수 있음.

μ˜ˆμ‹œ μ½”λ“œ

# ν•΄μ‹œλ§΅ μ˜ˆμ‹œ
my_dict = {'apple': 3, 'banana': 2, 'orange': 5}
print(my_dict.get('apple'))  # 3
print(my_dict.get('grape', 0))  # 0

# ν•΄μ‹œμ…‹ μ˜ˆμ‹œ
my_set = {1, 2, 3, 4}
my_set.add(5)
print(my_set)  # {1, 2, 3, 4, 5}

# ꡐ집합 κ΅¬ν•˜κΈ°
set1 = {1, 2, 3}
set2 = {2, 3, 4}
print(set1.intersection(set2))  # {2, 3}

# 단어 μΆœν˜„ 횟수 μ„ΈκΈ°
words = ["apple", "banana", "apple", "orange"]
word_count = {}
for word in words:
    word_count[word] = word_count.get(word, 0) + 1
print(word_count)  # {'apple': 2, 'banana': 1, 'orange': 1}

μœ„μ˜ λ‚΄μš©μ„ μ°Έκ³ ν•˜μ—¬ μ½”λ”©ν…ŒμŠ€νŠΈμ—μ„œ ν•΄μ‹œμ™€ κ΄€λ ¨λœ 문제λ₯Ό 효율적으둜 ν•΄κ²°ν•  수 있음.