🚧

ν•΄μ‹œ ν…Œμ΄λΈ”(Hash Table)

purpplee 2021. 12. 2. 17:31

ν•΄μ‹œ ν…Œμ΄λΈ”μ΄λž€?

ν•΄μ‹œ ν…Œμ΄λΈ”μ€ key - value μ‹œμŠ€ν…œμ˜ μžλ£Œκ΅¬μ‘°λ‹€λ‹€. key λŠ” λ°°μ—΄μ˜ index 처럼 value 에 λ°”λ‘œ μ ‘κ·Όν•  수 μžˆλ„λ‘ ν•˜λŠ” 값이닀. index 와 달리 λ¬Έμžμ—΄, 파일 λ“± λ‹€μ–‘ν•œ 데이터가 κ°€λŠ₯ν•΄μ„œ value와 κ΄€λ ¨ μžˆλŠ” κ°’μœΌλ‘œ μ„€μ •ν•  수 μžˆλ‹€.

fruits = {
	key: "사과", value: "λ§›μžˆλ‹€",
    key: "λ³΅μˆ­μ•„", value: "λ”±λ”±ν•œκ²Œ λ§›μžˆλ‹€."
}

//keyκ°’μœΌλ‘œ 데이터 λ°”λ‘œ μ ‘κ·Ό
fruits["사과"] -> "λ§›μžˆλ‹€"

 

μ–΄λ–»κ²Œ κ°€λŠ₯ν•˜μ§€?

사싀 ν•΄μ‹œν…Œμ΄λΈ”μ˜ λ‚΄λΆ€λŠ” λ°°μ—΄κ³Ό λΉ„μŠ·ν•˜κ²Œ index 와 value 둜 κ΅¬μ„±λ˜μ–΄ μžˆλ‹€. key λŠ” hash function 을 톡해 ν•΄μ‹œ μ½”λ“œλ‘œ κ³„μ‚°λ˜κ³ , 이 ν•΄μ‹œμ½”λ“œλŠ” index 둜 ν™˜μ‚°λœλ‹€. hash function 은 μž…λ ₯λ˜λŠ” λ°μ΄ν„°μ˜ 길이가 μ–Όλ§ŒνΌμ΄λ“  상관없이 κ³ μ •λœ 길이의 μ½”λ“œλ‘œ λ°˜ν™˜μ‹œμΌœμ£ΌλŠ” ν•¨μˆ˜λ‹€. 그리고 μ΄λ ‡κ²Œ κ³„μ‚°ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ„ hash algorithm 이라고 ν•œλ‹€. (참고둜 hash λŠ” κ°€λ³€ 길이의 데이터λ₯Ό κ³ μ •κΈΈμ΄λ‘œ ν™˜μ‚°ν•œ 값을 μ˜λ―Έν•œλ‹€.)

Hash Function

μ•„μ£Ό κ°„λ‹¨ν•œ hash algorithm 은 λ‚΄λΆ€ buckets 이라 λΆˆλ¦¬λŠ” 데이터 μ €μž₯μ†Œμ˜ μ‚¬μ΄μ¦ˆλ§ŒνΌ λ‚˜λˆˆ λ‚˜λ¨Έμ§€(λ‚˜λ¨Έμ§€λŠ” 무쑰건 λ‚˜λˆ„λŠ” 수 μ΄ν•˜μ˜ 값이 λ‚˜μ˜¨λ‹€.)λ₯Ό index 둜 μ“°λŠ” 것이닀. 

const bucketSize = 3;

hash_function(data) {
	const index = data % bucketSize;
    
	return index;
}


hash_function(24) = 24%3 = 0
hash_function(20) = 20%3 = 2
hash_function(16) = 16%3 = 1

λ¬Έμ œλŠ” μ•„λž˜ 같이, λ‹€λ₯Έ 데이터인데 같은 index 값이 λ‚˜μ˜€λŠ” κ²½μš°κ°€ μžˆλ‹€. 이런 상황을 Collision 이라고 ν•œλ‹€. 

hash_function(15) = 15%3 = 0
hash_function(21) = 21%3 = 0

 

Collision

Collision 이 λ°œμƒν•˜λ©΄ λŒ€ν‘œμ μœΌλ‘œ 두 가지 해결책을 μ“΄λ‹€. μ²«λ²ˆμ§ΈλŠ” 곡간을 같이 κ³΅μœ ν•˜λŠ” 것이고 λ‘λ²ˆμ§ΈλŠ” λΉ„μ–΄μžˆλŠ” λ‹€λ₯Έ 곡간에 λ„£λŠ” 것이닀.

 

해결법1. Chaning

Collision 이 λ°œμƒν•œ 데이터듀이 곡간을 같이 κ³΅μœ ν•œλ‹€. 보톡 Linked List 둜 μ„ μ–Έλœλ‹€. 검색을 ν•˜λŠ” 경우 ν•΄λ‹Ή index 둜 μ ‘κ·Όν•˜κ³  κ·Έ κ³΅κ°„μ—μ„œ μ„ ν˜•κ²€μƒ‰μ„ ν•œλ‹€. λ”°λΌμ„œ ν•΄μ‹œν…Œμ΄λΈ”μ˜ νš¨μœ¨μ€ 평균 O(1) μ΄μ§€λ§Œ, μ΅œμ•…μ˜ 경우 O(n) 이 λœλ‹€.

 

해결법2. Open Addressing

λΉ„μ–΄μžˆλŠ” λ‹€λ₯Έ 곡간을 μ°Ύμ•„ λ„£λŠ”λ‹€. λΉ„μ–΄μžˆλŠ” 곡간을 μ°ΎλŠ” 방법은 μ•„λž˜ μ„Έ 가지가 μžˆλ‹€.

  • Linear Probing : λ°”λ‘œ λ‹€μŒ 칸에 λ„£λŠ”λ‹€. κ·Έ 칸이 λΉ„μ–΄μžˆμ§€ μ•Šλ‹€λ©΄ κ·Έ λ‹€μŒ λΉ„μ–΄μžˆλŠ” 칸을 μ°ΎλŠ”λ‹€. κ²€μƒ‰ν•˜λŠ” 경우 key 둜 ν™˜μ‚°ν•œ index 에 μ ‘κ·Όν•΄μ„œ, κ²€μƒ‰ν•˜λ €λŠ” 데이터가 μ•„λ‹ˆλΌλ©΄ λ‹€μŒμΉΈμ„ κ²€μƒ‰ν•œλ‹€.
  • Quadratic probing : Linear Probing 은 +1 칸을 μ°ΎλŠ”λ°, Quadratic 은 1^2μΉΈ, 2^2μΉΈ, 3^2 μΉΈκ³Ό 같이 제곱수만큼 μ°¨μ΄λ‚˜λŠ” 칸을 탐색해 λΉ„μ–΄μžˆλŠ” 곳에 λ„£λŠ”λ‹€. 이 경우 같은 index 둜 ν™˜μ‚°λœ λ°μ΄ν„°λ“€μ˜ 이동폭이 κ°™μ•„μ§€λŠ” ν΄λŸ¬μŠ€ν„°λ§ λ¬Έμ œκ°€ 생긴닀.
  • Double hashing probing : ν΄λŸ¬μŠ€ν„°λ§ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ ν•΄μ‹œ ν•¨μˆ˜λ₯Ό 2개 λ‘”λ‹€. ν•˜λ‚˜λŠ” indexκ°’ ν™˜μ‚°μš©μ΄κ³ , λ‹€λ₯Έ ν•˜λ‚˜λŠ” Collision λ°œμƒ μ‹œ λΉ„μ–΄μžˆλŠ” 칸을 μ°ΎλŠ” 데 μ‚¬μš©ν•  칸수λ₯Ό κ³„μ‚°ν•˜λŠ” ν•¨μˆ˜λ‹€. 즉, h2(key) 만큼 μ΄λ™ν•˜λ©° λΉ„μ–΄μžˆλŠ” 칸을 μ°ΎλŠ”λ‹€.

 

쒋은 Hash Altorithm μ΄λž€...

Collision 이 λ„ˆλ¬΄ 자주 μΌμ–΄λ‚˜μ„œ 데이터가 ν•œ κ³΅κ°„μ—λ§Œ μ§‘μ€‘λ˜λ©΄ ν•΄μ‹œ ν…Œμ΄λΈ”μ˜ 효율이 λ–¨μ–΄μ§ˆ 것이닀. κ·ΈλŸ¬λ―€λ‘œ Collision 이 덜 λ°œμƒν•  수 μžˆλ„λ‘ hash algorithm 을 잘 μ§œμ•Όν•œλ‹€.(key-index κ°€ 1:1둜 λ‚˜μ˜€λŠ” μ™„λ²½ν•œ μ•Œκ³ λ¦¬μ¦˜μ€ ν•˜λŠ˜μ˜ 별따기닀...) 이미 μ—¬λŸ¬ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄κ°€ hash table 을 μ§€μ›ν•˜κ³  있고, λ˜‘λ˜‘ν•œ μ‚¬λžŒλ“€μ΄ λ§Œλ“  hash algorithm 듀이 λ§ŽμœΌλ‹ˆ μ°Έκ³ ν•˜λ©΄ 쒋을 것이닀.

 

ν•΄μ‹œν…Œμ΄λΈ” vs λ°°μ—΄

ν•΄μ‹œ ν…Œμ΄λΈ”μ€ λ‚΄λΆ€μ μœΌλ‘œ λ°°μ—΄κ³Ό 같은 ꡬ쑰이닀. hash_function(key) 을 톡해 ν™˜μ‚°λœ index 둜 데이터에 λ°”λ‘œ μ ‘κ·Όν•˜κ³ , λ‚΄λΆ€ 데이터 κ³΅κ°„μ˜ μ‚¬μ΄μ¦ˆκ°€ μ •ν•΄μ Έ μžˆλ‹€. κ·ΈλŸ¬λ‚˜ λ°°μ—΄μ˜ index λŠ” 0으둜 μ‹œμž‘ν•˜λŠ” μ •μˆ˜μ΄λ―€λ‘œ value 와 연관관계가 μ—†μ–΄μ„œ value λ₯Ό 찾으렀면 곡간을 ν•˜λ‚˜ν•˜λ‚˜ 탐색해야 ν•œλ‹€. ν•΄μ‹œ ν…Œμ΄λΈ”μ€ value 와 κ΄€λ ¨μžˆλŠ” key 둜 λ°”λ‘œ μ ‘κ·Όν•  수 있기 λ•Œλ¬Έμ— 배열보닀 탐색이 더 λΉ λ₯΄λ‹€.

 

ν•΄μ‹œ ν…Œμ΄λΈ” Resize

μ•„κΉŒ μ–ΈκΈ‰ν–ˆλ“― ν•΄μ‹œ ν…Œμ΄λΈ”μ˜ Bucket 의 μ‚¬μ΄μ¦ˆλŠ” 미리 정해진닀. 정해진 μ‚¬μ΄μ¦ˆμ˜ 곡간을 효율적으둜 쓰고싢을 λ•Œ ν•΄μ‹œν…Œμ΄λΈ” 자료ꡬ쑰λ₯Ό μ΄μš©ν•˜λ©΄ μ’‹λ‹€. κ·ΈλŸ¬λ‹€ μž…λ ₯λ˜λŠ” λ°μ΄ν„°μ˜ 양이 더 λ§Žμ•„μ Έμ„œ 곡간이 λΆ€μ‘±ν•œ κ²½μš°κ°€ μƒκΈ°λŠ”λ°, 이럴 λ•Œ ν•΄μ‹œ ν…Œμ΄λΈ”μ˜ μ‚¬μ΄μ¦ˆλ₯Ό λŠ˜λ¦¬λŠ” 방법이 μžˆλ‹€. 보톡 일정 개수 이상(보톡 75%정도 μ°¨λ©΄) 이 되면 버킷 μ‚¬μ΄μ¦ˆλ₯Ό 2배둜 λŠ˜λ¦°λ‹€. 0.75 수치λ₯Ό load factor 라고 ν•œλ‹€.

λ°˜μ‘ν˜•