MapleStory Finger Point

[자료구조] #6_2 해시 테이블

2021. 5. 30. 22:52Problem Solving/Data Structure

** 충돌(Collision) 해결 알고리즘

1) Chaining 기법

  • Open hashing 기법 중 하나로 해시 테이블 저장공간 외의 공간을 활용
  • 충돌시,  링크드 리스트로 데이터로 연결시켜서 저장함

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(len(hash_table[hash_address])):
            if hash_table[hash_address][index][0] == index_key:
                hash_table[hash_address][index][1] = value
                return
        hash_table[hash_address].append([index_key, value])
    else:
        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


 

2) Linear Probing 기법

  • Close Hashing 기법 중 하나로 해시 테이블 저장공간 안에서 충돌 문제를 해결
  • 충돌시, 해당 해시 주소의 다음 주소부터 이동하여 빈 공간이 나오면 저장
  • 저장공감 활용도를 높임

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)):
            if hash_table[index] == 0:
                hash_table[index] = [index_key, value]
                return
            elif hash_table[index][0] == index_key:
                hash_table[index][1] = value
                return
    else:
        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:
                return None
            elif hash_table[index][0] == index_key:
                return hash_table[index][1]
    else:
        return None

 

+) 빈번한 충돌을 개선하는 기법

hash_table = list([None for i in range(16)]) # 해시 테이블 저장공간 확대

def hash_function(key): 

       return key % 16 # 해시 함수 재정의


 

 

** 파이썬과 해시 함수

  • 파이썬의 hash() 함수는 실행할 때마다, 값이 달라질 수 있음
  • SHA(Secure Hash Algorithm): 어떤 데이터도 유일한 고정된 크기의 고정값을 리턴

ex) SHA-1

import hashlib

data = 'test'.encode()
hash_object = hashlib.sha1()
hash_object.update(data)
hex_dig = hash_object.hexdigest()

print (hex_dig) # a94a8fe5ccb19ba61c4c0873d391e987982fbbd3

 

ex) SHA-256

import hashlib

data = 'test'.encode()
hash_object = hashlib.sha256()
hash_object.update(data)
hex_dig = hash_object.hexdigest()

print (hex_dig) # 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08


 

 

** 응용

  • Chaining 기법을 적용한 해시 테이블 관리 + sha256 해시 알고리즘을 사용한 키 생성 함수

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)

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)):
            if hash_table[index] == 0:
                hash_table[index] = [index_key, value]
                return
            elif hash_table[index][0] == index_key:
                hash_table[index][1] = value
                return
    else:
        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:
                return None
            elif hash_table[index][0] == index_key:
                return hash_table[index][1]
    else:
        return None


 

 

** 시간 복잡도

  • 일반적인 경우(충돌이 발생하지 않음): O(1)
  • 최악의 경우(충돌이 모두 발생): O(n)

 

해시 테이블의 경우, 일반적인 경우를 기대하고 만들기 때문에, 시간 복잡도는 O(1) 이라고 말할 수 있음

 

'Problem Solving > Data Structure' 카테고리의 다른 글

[자료구조] #7_2 트리  (0) 2021.05.30
[자료구조] #7_1 트리  (0) 2021.05.30
[자료구조] #6_1 해시 테이블  (0) 2021.05.30
[자료구조] #5 시간 복잡도  (0) 2021.05.30
[자료구조] #4_3 링크드 리스트  (0) 2021.05.30