자료구조 & 알고리즘

[자료구조] 해시함수(Hash Function) 충돌(Collision) - 체이닝 해시테이블(1)

진기명기 2023. 4. 20. 15:42

✅ 해시함수 충돌 해결방법으로 지난 포스팅에서 '선형조사법'에 대해 다뤘었다. 아래 자료 참고 ⬇️

 

👉🏻 충돌이 생기는 이유

https://cyjcyj.tistory.com/123

 

[자료구조] 해시함수(Hash Function) 충돌(Collision) - 선형조사법(1)

❗️ 해시함수를 사용하면 빠른 속도로 특정 값을 신속하게 찾아 성능을 높일 수 있지만, 충돌이 일어날 수 있어 이를 항상 대비하며 사용해야 한다. 충돌이란?! 아래에서 다뤄보고자 한다. 지난

cyjcyj.tistory.com

 

👉🏻 해결방법 '선형조사법'

https://cyjcyj.tistory.com/124

 

[자료구조] 해시함수(Hash Function) 충돌(Collision) - 선형조사법(2)

🥹 지난 시간 작성했던 해시함수 충돌에 대한 해결방법인 선형 조사법에 대해 이어서 메서드를 구현해보려고 한다. 이번 포스팅에서 작성할 메서드는 remove()와 get() ❗️ 해시함수 충돌과 해결

cyjcyj.tistory.com

 

 

 


✅ 이번 포스팅에서는 해시함수 충돌의 또 다른 해결 방법인 '체이닝 해시테이블'에 대해서 정리할 계획이다.

 

 

💡 충돌 해결 방법 

체이닝 해시테이블(Chaining Hash Table) : 해시테이블 기반 자료구조

> 연결 리스트를 병합 사용하여 Hash 충돌을 해결

 

🫠 체이닝 해시테이블의 다양한 메서드 구현 

const HASH_SIZE = 37

// Element() : key, value 저장을 위한 생성자
function Element(key, value){
  this.key = key
  this.value = value
}

// ChainingHashTable() : 생성자
function ChainingHashTable(){
  this.table = new Array(HASH_SIZE)
  this.length = 0
}

// hashCode() : 해시 함수
ChainingHashTable.prototype.hashCode = function(key){
  let hash = 0

  for(let i = 0; i < key.length; i++){
    hash += key.charCodeAt(i)
  }
  
  return hash % HASH_SIZE // hash에 대한 모듈러를 통해서 HASH_SIZE 이하의 숫자로 반환
}
✅ 체이닝 해시테이블 생성자함수 및 해당 prototype은 앞 포스팅과 많이 반복되기 때문에 따로 설명 ❌

 

 

❗️ 출력해 보자

// ChainingHashTable 생성
let cht1 = new ChainingHashTable()

console.log(cht1) // ChainingHashTable { table: [ <37 empty items> ], length: 0 }

 

 

 


🧐 체이닝 해시테이블은 연결리스트를 병합해서 충돌을 해결한다고 했는데, 연결리스트를 어떻게 가져올까?

✅ 아래 링크를 통해 만들었던 LinkedList를 import 해서 가져오면 된다. 

✅ 기존에 작성한 LinkedList의 생성자 함수와 메서드를 사용하기 위해 .mjs 확장명으로 변경 후, 해당 파일 export 해준다.

import { LinkedList } from '../../파일 위치'

// LinkedList와 병합
let ll = new LinkedList()
ll.append(new Element('Ana', 172))

console.log(ll)
/*
LinkedList {
  head: Node { data: Element { key: 'Ana', value: 172 }, next: null },
  length: 1
}
*/
✅ LinkedList를 import해온 뒤, LinkedList의 head에 Element로 준 인자값이 들어가도록 구현하였다. 

 

💛 LinkedList의 append 메서드 해석 링크 ⬇️

https://cyjcyj.tistory.com/97

 

[자료구조] 선형자료구조 연결리스트(Linked List)에 노드(Node) 추가하기

🫠 선형자료구조 - 연결리스트(Linked List)에 노드 추가하기 ❗️prototype을 이용한 노드와 연결리스트 생성 방법 먼저 확인하고 오자! https://cyjcyj.tistory.com/95 [자료구조] 선형자료구조 프로토타입

cyjcyj.tistory.com

 

 

 

 


🫠 연결리스트와 병합한 체이닝 해시테이블의 메서드를 구현해 보자 

// clear() : 초기화
ChainingHashTable.prototype.clear = function(){
  this.table = new Array(HASH_SIZE)
  this.length = 0
}

// size() : 크기 반환
ChainingHashTable.prototype.size = function(){
  return this.length
}
✅ 초기화, 크기 반환 메서드는 간단하면서도 계속적으로 반복되는 코드이기 때문에 따로 설명하지 ❌

 

 

 

// put() : 데이터 추가
ChainingHashTable.prototype.put = function(key, value){
  let index = this.hashCode(key)
  console.log(`key : ${key} -> index : ${index}`)

  if(this.table[index] === undefined){ // 해당 위치 빈공간일 경우
    this.table[index] = new LinkedList() // LinkedList 생성
  }

  // LinkedList의 append 메서드 사용하여 데이터 추가
  this.table[index].append(new Element(key, value))
  this.length++

  return true
}
✅ 인자값으로 주어지는 key의 해시코드에 해당하는 index가 비어있다면 LinkedList를 생성해 준다.
LinkedList의 메서드인 append를 사용하여 해당 index에 데이터를 추가한 후, 길이를 +1 증가시킨다. 

 

 

 

❗️ 출력해 보자

// 체이닝 해시테이블 생성
let cht2 = new ChainingHashTable()

// 데이터 추가
cht2.put('Ana', 173)
cht2.put('Donnie', 183)
cht2.put('Sue', 179)
cht2.put('Jamie', 190)
cht2.put('Paul', 168)
/*
key : Ana -> index : 13
key : Donnie -> index : 13
key : Sue -> index : 5
key : Jamie -> index : 5
key : Paul -> index : 32
*/

// 해시테이블 조회
console.log(cht2)
/*
ChainingHashTable {
  table: [
    <5 empty items>,
    LinkedList { head: [Node], length: 2 }, // LinkedList의 길이: 2 (Sue와 Jamie)
    <7 empty items>,
    LinkedList { head: [Node], length: 2 }, // (Ana와 Donnie)
    <18 empty items>,
    LinkedList { head: [Node], length: 1 },
    <4 empty items>
  ],
  length: 5
}
*/
✅ 출력 결과를 보면 Sue와 Jamie가 index:5의 값으로 같은 위치에 해당하고, Ana와 Donnie가 index:13으로 충돌된 것을 확인할 수 있다.
✅ 하지만 LinkedList를 통해 각 해당 위치에 충돌된 2개의 데이터를 넣어 충돌을 해결하였다.
✅ 데이터가 충돌하여 같은 index에 들어간 Sue와 Jamie, Ana와 Donnie의 LinkedList의 길이가 2인 것을 확인할 수 있다. 

 

 

 

🫠 다음 포스팅에서는 체이닝 해시테이블의 추가/삭제 등 또 다른 메서드를 구현해 보고, 확인해 볼 것이다!