해시 테이블은 (Key, Value)쌍으로 저장하는 자료 구조이다.
해시 테이블의 데이터에 접근하는 방식은 다음과 같다.

그림과 같이 ("John Smith", "521-1234") 데이터를 16 크기를 가진 해시 테이블에 저장한다고 하자.
def hash_func(key):
return (key - 8) % 16 # ord()는 문자의 ASCII 값을 찾아준다.
"John Smith"에 해시 함수를 적용하여 index를 찾은 후, 찾은 index에 데이터를 저장한다.def save_data(data, value):
key = ord(data[0]) # 74
hash_address = hash_func(key) # 2
hash_table[hash_address] = value
save_data("John Smith", "521-1234")
검색할 데이터에 대해 해시 함수를 적용하여 index를 찾은 후 해당 index의 데이터를 불러온다.
def get_data(data):
key = ord(data[0])
hash_address = hash_func(key)
return hash_table[hash_address]
get_data("John Smith")
장점
단점
해시 테이블의 가장 큰 문제는 충돌이다. 예를 들어 위 예에서 "James Malin"를 추가하여 해시 함수를 돌려보면 "John Smith"의 index 값 2와 충돌하게 된다.
이러한 충돌을 해결하기 위해 크게 2가지를 적용해볼 수 있다.

해시 테이블의 저장공간 외의 공간을 활용하는 기법이다. 충돌이 일어나면 링크드 리스트같은 자료구조를 사용하여 데이터를 추가를 뒤에 연결시키는 기법이다.
다음과 같이 연결할 수 있다.
hash_table = [0 for i in range(8)]
# [0, 0, 0, 0, 0, 0, 0, 0]
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:
hash_table[hash_address].append([index_key, value]) # chaining
else:
hash_table[hash_address] = [[index_key, value]] # insert
save_data('Dd', '1201')
save_data('Data', '3301')
print(hash_table)
# [[[-3861416235556576752, '1201'], [6581991383312608576, '3301']], 0, 0, 0, 0, 0, 0, 0]
추가 메모리를 사용하는 Chaining 방식과 달리 해시 테이블의 공간을 활용하는 방법

hash() 함수는 실행될 때마다 값이 달라질 수 있다.
SHA(Secure Hash Algorithm)같은 해시 함수는 유일한 고정된 크기의 고정값을 return한다.
SHA-1
import hashlib
hash_object = hashlib.sha1()
hash_object.update('test'.encode())
hex_dig = hash_object.hexdigest()
print(hex_dig)
# a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
SHA-256
import hashlib
hash_object = hashlib.sha256()
hash_object.update('test'.encode())
hex_dig = hash_object.hexdigest()
print(hex_dig)
# 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08