๋ฐ์ํ
๐Hash ๊ตฌ์กฐ
- Hash Table: key์ data(value)๋ฅผ ์ ์ฅํ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ
- ex) Python์ Dictionary : key์ value๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ ํ์ ์ผ๋ก, key๊ฐ์ ํตํด value๋ฅผ ๋ฐ๋ก ๊บผ๋ผ ์ ์์ (Python์์๋ hash๊ตฌํ ์์ด ๋ฐ๋ก dictionary ์ฌ์ฉํ๋ฉด ๋จ)
- ๋ณดํต ๋ฏธ๋ฆฌ hash table์ ํฌ๊ธฐ๋งํผ ๋ฐฐ์ด ์์ฑ ํ ์ฌ์ฉ (๊ณต๊ฐ๊ณผ ํ์ ์๊ฐ์ ๋ง๋ฐ๊พธ๋ ๊ธฐ๋ฒ)
๐์ฉ์ด
- hash: random ๊ฐ์ ๊ณ ์ ๊ธธ์ด๋ก ๋ณํํ๋ ๊ฒ (๋จ๋ฐฉํฅ ์ํธํ ๊ธฐ๋ฒ์ผ๋ก, ํด์ ์๊ณ ๋ฆฌ์ฆ์ ์ด์ฉํ์ฌ ๊ณ ์ ๋ ๊ธธ์ด์ ์ํธํ๋ ๋ฌธ์์ด๋ก ๋ณํ)
- hash table:
- hashing function: key์ ๋ํด ์ฐ์ ์ฐ์ฐ์ ์ด์ฉํด ๋ฐ์ดํฐ ์์น๋ฅผ ์ฐพ์ ์ ์๋ ํจ์, ์ฆ ์์ด์ด ๊ธธ์ด์ ๋ฐ์ดํฐ๋ฅผ ๊ณ ์ ๋ ๊ธธ์ด์ ๋ฐ์ดํฐ๋ก ๋งคํํ๋ ํจ์ (key๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์ hash table์ ํน์ ์ฃผ์๊ฐ(hash value / hash address)๋ฅผ return)
- key: ๋งคํ ์ ์๋ ๋ฐ์ดํฐ ๊ฐ
- hash value / hash address: ๋งคํ ํ ๋ฐ์ดํฐ ๊ฐ(key๋ฅผ hashing function์ผ๋ก ์ฐ์ฐํ์ฌ ๋์จ ๊ฐ), hash value๋ก hash table์์ ํด๋น key์ ๋ํ ๋ฐ์ดํฐ ์์น๋ฅผ ์ผ๊ด์ฑ์๊ฒ ๊ฒ์ ๊ฐ๋ฅ
- slot: ํ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ ์๋ ๊ณต๊ฐ
์์์ ๊ธธ์ด์ ๋ฐ์ดํฐ๋ฅผ ๊ณ ์ ๋ ๊ธธ์ด์ ๋ฐ์ดํฐ๋ก ๋งคํํ๋ ํจ์
๋งคํ ์ ์๋ ๋ฐ์ดํฐ์ ๊ฐ: key, ๋งคํ ํ ๋ฐ์ดํฐ์ ๊ฐ์ hash value, ๋งคํํ๋ ๊ณผ์ hashing
๐Hash Table์ ์ฅ๋จ์ ๊ณผ ์ฃผ์ ์ฉ๋
- ์ฅ์
- ๊ฒ์ ์๋๊ฐ ์์ฒญ ๋น ๋ฅด๋ค. (๋ฐ์ดํฐ ์ ์ฅ/์ฝ๊ธฐ ์๋๊ฐ ์์ฒญ ๋น ๋ฅด๋ค!)
(array์์ data๋ฅผ ์ฐพ์ผ๋ ค๋ฉด ์์์๋ถํฐ ์ญ์ฐ์ฐ-์ฑ ์ฐพ์์ผ ํ์ง๋ง hash table์์๋ data๋ฅผ ์ฝ์ผ๋ฉด ๊ทธ data์ ๋์ํ๋ key๋ฅผ ์๋์ผ๋ก ์ถ์ถํ๊ณ ๊ทธ key๋ฅผ hash function์ ๋ฃ์ด ๋ฐ์ดํฐ ์ ์ฅ ์์น๋ฅผ ๋ฐ๋ก ๋ฐํ๋ฐ์ ๊ณง๋ฐ๋ก ํ์์ด ๊ฐ๋ฅํ๋ค.) - ์ค๋ณต ์ฒ๋ฆฌ๊ฐ ์ฝ๋ค.
- ๊ฒ์ ์๋๊ฐ ์์ฒญ ๋น ๋ฅด๋ค. (๋ฐ์ดํฐ ์ ์ฅ/์ฝ๊ธฐ ์๋๊ฐ ์์ฒญ ๋น ๋ฅด๋ค!)
- ๋จ์
- ์ ์ฅ๊ณต๊ฐ์ด ๋ด๊ฐ ์ ์ฅํ๊ณ ์ ํ๋ data ์์ฒด์ size๋ณด๋ค ํฐ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค.
- ์ฌ๋ฌ ํค์ ํด๋นํ๋ ์ฃผ์๊ฐ ๋์ผํ ๊ฒฝ์ฐ ์ถฉ๋์ ํด๊ฒฐํ๊ธฐ ์ํ ๋ณ๋ ์๋ฃ๊ตฌ์กฐ๊ฐ ํ์ํ๋ค. (-> ์ถฉ๋ ํด๊ฒฐ์ ์ํ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ๋จ์ํ ์ ์ฅ๊ณต๊ฐ์ ๋๋ฆฌ๋ ๊ฒ์ด๋ค.)
- ์ฃผ์ ์ฉ๋
- ๊ฒ์์ด ํ์ํ ๊ฒฝ์ฐ
- ์ ์ฅ, ์ญ์ , ์ฝ๊ธฐ๊ฐ ํ์ํ ๊ฒฝ์ฐ
- cash ๊ตฌํ์ด ํ์ํ ๊ฒฝ์ฐ (์ฌ์ด ์ค๋ณต ์ฒ๋ฆฌ)
๐Hash ๊ตฌํ
def get_key(data):
return hash(data)
def hash_function(key):
return key % 8 #8๋ก ๋๋ ๋๋จธ์ง๋ฅผ hash value๋ก
def save_data(data, value):
hash_address = hash_function(get_key(data)) #key๊ฐ์ hash function์ ๋ฃ์ด hash value(hash address)๊ฐ ๋ง๋ค๊ธฐ
hash_table[hash_address] = value
def read_data(data):
hash_address = hash_function(get_key(data))
return hash_table[hash_address]
- hash table size๋งํผ์ list๋ฅผ ๋ฏธ๋ฆฌ ์์ฑํด์ผ ํจ
- get_key(): python ๋ด์ฅ ํจ์ hash()๋ฅผ ์ด์ฉํด data์ ๊ณ ์ key๊ฐ์ ๋ฆฌํด ๋ฐ๋๋ค
- hash_function(): ๋๋จธ์ง ๊ฐ์ ์ด์ฉํ ์ด๊ฐ๋จ hash function
(hash function ๊ณ ์ ๊ธฐ๋ฒ์ ๋ค์ํ์ง๋ง ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ์์ division๋ฒ) - save_data(): data์ value๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ๊ณ , ํด๋น data์ ๋ํ key๋ฅผ hashing function์ผ๋ก hash ์ฃผ์๋ฅผ ํน์ ํ๊ณ ๊ฑฐ๊ธฐ์ value๋ฅผ ์ ์ฅํ๋ ํจ์
- read_data(): data๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ๊ณ , ํน์ ์ฃผ์์ ์ ์ฅ๋ data์ ํด๋นํ๋ value๊ฐ์ ๋ฆฌํดํ๋ ํจ์
๐Hash Collision ํด๊ฒฐ ์๊ณ ๋ฆฌ์ฆ
ํ ๊ฐ ์ด์์ data๊ฐ ์ค๋ณต๋์ด ๋์ผํ address์ ์ ์ฅ๋๋ ๊ฒฝ์ฐ, hash collision ๋ฐ์
1) Chaining ๊ธฐ๋ฒ
- Open Hashing ๊ธฐ๋ฒ (hash table ์ ์ฅ๊ณต๊ฐ ์ธ์ ๊ณต๊ฐ์ ํ์ฉํ๋ ๊ธฐ๋ฒ: ์ถฉ๋์ด ๋ฐ์ํ๋ฉด ์ถ๊ฐ ๊ณต๊ฐ์ ํ๋ณดํ์ฌ ์ ์ฅ)
- ์ถฉ๋์ด ์ผ์ด๋๋ฉด, linked list๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ๋ก ๋ค์ ์ฐ๊ฒฐ์์ผ์ ์ ์ฅํ๋ ๋ฐฉ๋ฒ
(linked list๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ฏธ๋ฆฌ ์ ์ฅ๊ณต๊ฐ์ ์ก์๋์ ํ์์์ด, ์ถฉ๋์ด ๋ ๋๋ง๋ค๋ง ์ถ๊ฐํ๋ฉด ๋จ)
๊ตฌํ
def get_key(data):
return hash(data)
def hash_function(key):
return key % 8
def save_data(data, value):
index_key = get_key(data) #key๋ฅผ ๋ณ๋์ ๋ณ์์ ์ ์ฅ
hash_address = hash_function(index_key)
if hash_table[hash_address] != 0: #hash table์ data๊ฐ ๋ค์ด์์ผ๋ฉด (์ถฉ๋์ด ๋ฐ์ํ๋ฉด)
for index in range(len(hash_table[hash_address])): #์ง๊ธ ์ถฉ๋์ด ์ผ์ด๋ address์ data๊ฐ ์ผ๋ง๋ ์ ์ฅ๋์ด ์๋์ง ํ์ธ
if hash_table[hash_address][index][0] == index_key: #key๊ฐ์ด ์ค๋ณต์ด๋ฉด value๋ฅผ update
hash_table[hash_address][index][1] = value
return
hash_table[hash_address].append([index_key, value]) #key๊ฐ์ด ์ค๋ณต์ด ์๋๋ฉด append(๋ค์ ์ถ๊ฐ) -> ํ๋์ slot์ ์ชผ๊ฐ์ key, value๋ฅผ ๊ฐ๊ฐ ์ ์ฅ(list์์ list)
else: #slot์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด(์ถฉ๋์ด ์์ผ๋ฉด) ๊ทธ๋ฅ ๋ฐ๋ก ๋ฃ๊ธฐ
hash_table[hash_address] = [[index_key, value]]
def read_data(data):
index_key = get_key(data)
hash_address = hash_function(index_key)
if hash_table[hash_address] != 0:
for index in range(len(hash_table[hash_address])):
if hash_table[hash_address][index][0] == index_key:
return hash_table[hash_address][index][1]
return None
else:
return None
save_data()
- ๊ณ ์ key๊ฐ์ value๊ฐ ๋ค์ด์๋ slot์ ๊ฐ์ด ์ ์ฅํด์ผ ํ๊ธฐ ๋๋ฌธ์
index_key
๋ณ์์ ๋ฐ๋ก ์ ์ฅํด์ผ ํ๋ค. -> ๊ฐ์ adress์ ์ ์ฅ๋์ด ์์ ๋index_key
๋ก ๋ด๊ฐ ์ํ๋ ๊ฐ์ ํ์ํด์ผ ํ๊ฒ ๋๋ฌธ - ์ฒซ๋ฒ์งธ if๋ฌธ์ ์ถฉ๋์ด ์ผ์ด๋๋์ง, ์๋์ง๋ฅผ ํ์ธํ๊ธฐ ์ํจ
- ์ถฉ๋์ด ์ผ์ด๋๋ฉด, for๋ฌธ์ ํตํด ์ถฉ๋์ด ์ผ์ด๋ address์ ํ์ฌ ๋ฐ์ดํฐ๊ฐ ์ผ๋ง๋ ์ ์ฅ๋์ด ์๋์ง ํ์ธ
- address๊ฐ ๊ฐ์ผ๋ฏ๋ก ํ์์ ์ํด์ ํ๋์ slot์ key์ value๊ฐ์ ๊ฐ์ด ์ ์ฅํด ์ฃผ์ด์ผ ํจ (list์์ list)
read_data()
- for๋ฌธ์ผ๋ก ๋ด๊ฐ ์ฝ์ด์ค๊ณ ์ถ์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ธฐ๊น์ง ๋ฐ๋ณต๋ฌธ ์ํ
2) Linear Probing ๊ธฐ๋ฒ
- Close Hashing ๊ธฐ๋ฒ (hash table ์ ์ฅ๊ณต๊ฐ ๋ด์ ๊ณต๊ฐ์ ํ์ฉํ๋ ๊ธฐ๋ฒ: ์ถฉ๋์ด ๋ฐ์ํ๋ฉด hash table์์ ๋ฐ ๊ณต๊ฐ์ ์ฐพ์์ ๊ฑฐ๊ธฐ์ ์ ์ฅํ๋ ๋ฐฉ๋ฒ)
- ์ถฉ๋์ด ์ผ์ด๋๋ฉด, ํด๋น hash address์ ๋ค์ address๋ถํฐ ๋งจ ์ฒ์ ๋์ค๋ ๋น ๊ณต๊ฐ์ ์ ์ฅ(์ ์ฅ๊ณต๊ฐ ํ์ฉ๋๋ฅผ ๋์ด๊ธฐ ์ํ ๊ธฐ๋ฒ)
๊ตฌํ
hash_table = list([0 for i in range(8)])
def get_key(data):
return hash(data)
def hash_function(key):
return key % 8
def save_data(data, value):
index_key = get_key(data)
hash_address = hash_function(index_key)
if hash_table[hash_address] != 0:
for index in range(hash_address, len(hash_table)): #ํ์ฌ address๋ถํฐ hash table์ ๋๊น์ง ๋ฐ๋ณตํ๋ฉด์
if hash_table[index] == 0: #๋น๊ณต๊ฐ ์ฐพ์ผ๋ฉด
hash_table[index] = [index_key, value] #๊ฑฐ๊ธฐ์ ๋ฐ์ดํฐ ๋ฃ๊ธฐ
return
elif hash_table[index][0] == index_key: #key์์ฒด๊ฐ ๊ฐ์ผ๋ฉด value update
hash_table[index][1] = value
return
else: #ํด๋น address์ data๊ฐ ์์ ์์ -> ๋ฐ๋ก ๋ฃ์ผ๋ฉด ๋จ (์ถฉ๋ ๋ฐ์ X)
hash_table[hash_address] = [index_key, value]
def read_data(data):
index_key = get_key(data)
hash_address = hash_function(index_key)
if hash_table[hash_address] != 0:
for index in range(hash_address, len(hash_table)):
if hash_table[index] == 0: #adress์ ๊ฐ์ด ์๊ธด ์๋๋ฐ ๋ด๊ฐ ์ฐพ๋ ๊ฐ์ ์์
return None
elif hash_table[index][0] == index_key:
return hash_table[index][1]
else: #์ฝ์ด์ฌ data ์์ฒด๊ฐ ์์ ์์
return None
save_data()
- ์ถฉ๋ํ data๋ฅผ ๋ค๋ฅธ ๊ณต๊ฐ์ ๋ฃ์ด์ผ ํ๋ฏ๋ก chaining ๊ธฐ๋ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก data์ ๊ณ ์ ํ key๋ ํจ๊ป ์ ์ฅํด์ฃผ์ด์ผ ํจ (address๊ฐ ๊ฐ์ผ๋ฏ๋ก ํ์์ ์ํด์ ํ๋์ slot์ key์ value๊ฐ์ ๊ฐ์ด ์ ์ฅํด ์ฃผ์ด์ผ ํจ (list์์ list))
- ์ฒซ๋ฒ์งธ if๋ฌธ์ ์ถฉ๋์ด ์ผ์ด๋๋์ง, ์๋์ง๋ฅผ ํ์ธํ๊ธฐ ์ํจ
- ์ถฉ๋์ด ์ผ์ด๋๋ฉด, for๋ฌธ์ ํตํด ํ์ฌ address๋ถํฐ hash table ๋๊น์ง ๋๋ฉด์ ๋น๊ณต๊ฐ์ ์ฐพ์ผ๋ฉด ๊ฑฐ๊ธฐ์ ๋ฐ์ดํฐ ๋ฃ๊ธฐ
- ๋ง์ฝ key์์ฒด๊ฐ ๋์ผํ๋ฉด data value๋ฅผ update
read_data()
- ์ฒซ๋ฒ์งธ if๋ฌธ์ data๊ฐ hash table์ ์๋์ง๋ฅผ ๊ฒ์
- for๋ฌธ์ผ๋ก hash table์ ๋๋ฉด์ ๋ด๊ฐ ์ฐพ๊ณ ์ถ์ ๋ฐ์ดํฐ ์ฐพ๊ธฐ
if hash_table[index] == 0
: ๊ฐ์ด 0์ด๋ผ๋ ๊ฑด ๋น๊ณต๊ฐ์ด๋ผ๋ ๋ป -> ๋น๊ณต๊ฐ์ด ๋์๋ค๋ฉด ์ด์ ์ ์ด๋ฏธ ์ฐพ์์ผ์ผ ๋๋๋ฐ, ๋น๊ณต๊ฐ์ด ๋์ฌ๋๊น์ง ์์ง๋ ๋ชป์ฐพ์๋ค๋ฉฐ ๋ด๊ฐ ์ฐพ๋ ๊ฐ์ด ์๋ค๋ ์๊ธฐ
๋น๋ฒํ ์ถฉ๋์ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ
- hashing function ์ฌ์ ์
- hash table ์ ์ฅ๊ณต๊ฐ ํ๋def hash_function(key):{% endhighlight %}
- => ์ ์ฅ๊ณต๊ฐ↑ → ์ถฉ๋↓, ํ์์๊ฐ↓ (:hash table์ ๊ณต๊ฐ๊ณผ ํ์์๊ฐ์ ๋ง๋ฐ๊พผ๋ค)
return key % 16
- {% highlight python %}
hash_table = list([None for i in range(16)])
๐hashing function๊ณผ ํค ์์ฑ ํจ์
- python์ hash()ํจ์๋ ์คํํ ๋๋ง๋ค, ๊ฐ์ด ๋ฌ๋ผ์ง ์ ์์
- ๋ฐ๋ผ์ SHA(Secure Hash Algorithm) ์ฌ์ฉ: ์ด๋ค ๋ฐ์ดํฐ๋ ์ ์ผํ ๊ณ ์ ๋ ํฌ๊ธฐ์ ๊ณ ์ ๊ฐ์ return
import hashlib
hash_table = list([0 for i in range(8)])
def get_key(data):
hash_object = hashlib.sha256()
hash_object.update(data.encode())
hex_dig = hash_object.hexdigest()
return int(hex_dig, 16)
๐์๊ฐ๋ณต์ก๋
- ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ(collision์ด ์๋ ๊ฒฝ์ฐ): $O(1)$ (-> ๋ฐ๋ก ํน์ ์์น์ ์ ์ฅํ๊ณ ๊ฒ์ํ๊ธฐ ๋๋ฌธ์)
- ์ต์ ์ ๊ฒฝ์ฐ(๋ชจ๋ collision์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ): $O(n)$
-> hash table์ ๊ฒฝ์ฐ, ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ฅผ ๊ธฐ๋ํ๊ณ ๋ง๋ค๊ธฐ ๋๋ฌธ์ ์๊ฐ ๋ณต์ก๋๋ $O(1)$์ด๋ผ๊ณ ํ ์ ์์
๊ฒ์์์ array์ ๋น๊ตํ๋ฉด
- 16๊ฐ์ ๋ฐฐ์ด์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ , ๊ฒ์: $O(n)$ (-> ๋ชจ๋ ํ๋ฒ์ฉ ์ํํด์ผ ํ๊ธฐ ๋๋ฌธ์)
- 16๊ฐ์ ๋ฐ์ดํฐ ์ ์ฅ๊ณต๊ฐ์ ๊ฐ์ง ํด์ฌ ํ ์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ , ๊ฒ์: $O(1)$
๋ฐ์ํ
'Algorithm > Data Structure' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Data Structure (5) Graph (๊ทธ๋ํ) (0) | 2021.05.08 |
---|---|
Data Structure - Heap (ํ) | Python ๊ตฌํ (0) | 2021.05.07 |
Data Structure (2) Tree (ํธ๋ฆฌ) (0) | 2021.05.07 |
Data Structure(1) Linked List (์ฐ๊ฒฐ ๋ฆฌ์คํธ) (0) | 2021.05.07 |
๋๊ธ