해시 테이블(Hash Table)
- 유일한 값(반복되지 않는 값)을 저장하기 위한 자료 구조입니다.
- 다양한 길이를 가진 데이터를 고정된 길이의 데이터로 바꿔 저장한 자료 구조입니다.
- 자바스크립트 객체와 같은 방식으로 key : 값 형식으로 저장됩니다.
해싱이란??
다양한 길이의 키(key) => 고정된 길이 해시(hash)로 바꿔주는 과정을 말합니다
해시 충돌
키(key)는 다른데 해시(hash)값이 똑같은 경우
ex)
11 % 2 == 1
21 % 2 == 1
해시 함수
키(key)를 해시(hash)로 바꿔주는 역할을 한다.
다양한 길이를 가지고 있는 키(key)를 고정된 길이를 가지는 해시(hash)로 변경하여
저장소(해시테이블)를 효율적으로 운영할 수 있도록 도와줍니다.
-
다양한 길이 : [... 3, ... 52 ... 50 ... 5004] - 데이터는 4개지만, 길이가 5005인 배열
(기존 데이터의 키(key)일 경우) -
고정된 길이 : [0(50), null, 2(52), 3(3), 4(5004)] - 데이터는 4개지만, 길이가 5인 배열
(해시함수를 통과한 hash일 경우)
좋은 해시함수 만드는 법
- 결정성 : 동일한 키는 동일한 해시 값을 만들어야 합니다.
- 균일한 분배 : 배열 전체를 최대한 효율적으로 활용해야 합니다.
- 키는 다른데 해시 값이 똑같은 경우 충돌을 피할 수 있게 생성해야 합니다.
해시테이블 장단점
장점
- 작은 저장소(해시 테이블)로 많은 데이터를 효율적으로 관리할 수 있습니다.
- index에 해시값을 사용하여서 모든 데이터를 살피지 않고 검색, 삽입, 삭제를 빠르게 수행할 수 있습니다.
- 길이가 서로 다른 데이터에 대해 일정한 길이로 만들 수 있어서 '데이터 축약' 기능도 수행 가능합니다.
단점
- 순서가 있는 배열에는 어울리지 않습니다.(순서와 상관없이 key를 hash로 바꿔주기 때문)
- 공간 효율성이 떨어집니다.(데이터가 저장되기 전에 미리 공간을 확보해야 하고, 공간이 부족한 경우 채워지지 않기 때문)
해싱 기법
- 선형 탐사 : 키가 다른데 동일한 해시값이 나온경우 hash + 1 하여 저장하는 기법
- 이차 탐사 : 키가 다른데 동일한 해시값이 나온 경우 hash + (중복된 횟수 제곱) 하여 저장하는 기법
- 이중 해싱 : 키가 다른데 동일한 해시값이 나온 경우 hash값을 한번더 해시함수를 이용하여 저장하는 기법
code
function hashTable(size) {
this.size = size;
this.keys = this.initArr(size);
this.values = this.initArr(size);
this.limit = 0;
}
hashTable.prototype.initArr = function(size) {
var arr = [];
for(var i=0; i<size; i++) {
arr.push(null);
}
return arr
}
hashTable.prototype.put = function(key, value) {
if(this.limit >= this.size) {
return console.log('더이상 추가 할 수 없습니다.')
}
var hashIndex = this.hash(key);
while(this.keys[hashIndex] !== null) {
hashIndex++
hashIndex = hashIndex%this.size;
}
this.keys[hashIndex] = key;
this.values[hashIndex] = value;
this.limit++;
}
hashTable.prototype.get = function(key) {
var hashIndex = this.hash(key);
while(this.keys[hashIndex] != key) {
hashIndex++
hashIndex = hashIndex%this.size;
}
return this.values[hashIndex];
}
hashTable.prototype.hash = function(key) {
if(!Number.isInteger(key)) {
return console.log('숫자가 아닙니다')
}
return key % this.size;
}
var test = new hashTable(13);
test.put(4, "kim");
test.put(13, "lee");
test.put(18, "you");
test.put(33, "heo");
test.put(59, "son");
test.put(82, "jung");
test.put(101, "seo");
test.put(109, "sad");
console.log(test)
// hashTable {
// size: 13,
// keys: [
// 13, null, null, null,
// 4, 18, 82, 33,
// 59, 109, 101, null,
// null
// ],
// values: [
// 'lee', null, null,
// null, 'kim', 'you',
// 'jung', 'heo', 'son',
// 'sad', 'seo', null,
// null
// ],
// limit: 8
// }
설명
1. HashTable 생성
function hashTable(size) {
this.size = size;
this.keys = this.initArr(size);
this.values = this.initArr(size);
this.limit = 0;
}
hashTable.prototype.initArr = function(size) {
var arr = [];
for(var i=0; i<size; i++) {
arr.push(null);
}
return arr
}
var test = new hashTable(13);
console.log(test)
// hashTable {
// size: 13,
// keys: [
// null, null, null,
// null, null, null,
// null, null, null,
// null, null, null,
// null
// ],
// values: [
// null, null, null,
// null, null, null,
// null, null, null,
// null, null, null,
// null
// ],
// limit: 0
// }
2. 추가
// 해시 테이블에 데이터를 추가하는 함수
hashTable.prototype.put = function(key, value) {
// size == 테이블 최대 크기
// limit == 현재 테이블 크기
if(this.limit >= this.size) {
return console.log('더이상 추가 할 수 없습니다.')
}
// 해싱 함수를 호출하여 key값을 => hash값으로 바꿈
var hashIndex = this.hash(key);
// 이미 해당 hash값이 있다면 +1 하여 저장
while(this.keys[hashIndex] !== null) {
hashIndex++
hashIndex = hashIndex%this.size;
}
// 중복되지 않은 해시값이 정해졋을때 hash값 : value 저장하고 현재 테이블 크기도 +1 해줌
this.keys[hashIndex] = key;
this.values[hashIndex] = value;
this.limit++;
}
// key => hash로 바꿔주는 함수
hashTable.prototype.hash = function(key) {
if(!Number.isInteger(key)) {
return console.log('숫자가 아닙니다')
}
return key % this.size;
}
test.put(4, "kim");
test.put(13, "lee");
test.put(18, "you");
test.put(33, "heo");
test.put(59, "son");
test.put(82, "jung");
test.put(101, "seo");
test.put(109, "sad");
3. 검색
// 해시 테이블에 해당 hash값을 가지고 있는지 검색하는 함수
hashTable.prototype.get = function(key) {
// 해싱 함수를 호출하여 key값을 => hash값으로 바꿈
var hashIndex = this.hash(key);
// 이미 해당 hash값이 있다면 +1하여 검색
while(this.keys[hashIndex] != key) {
hashIndex++
hashIndex = hashIndex%this.size;
}
console.log(this.values[hashIndex])
// 해당 key의 hash값을 찾았을때 value값을 return함
return this.values[hashIndex];
}
// key => hash로 바꿔주는 함수
hashTable.prototype.hash = function(key) {
if(!Number.isInteger(key)) {
return console.log('숫자가 아닙니다')
}
return key % this.size;
}
test.get(4, "kim");
test.get(13, "lee");
test.get(18, "you");
test.get(33, "heo");
test.get(59, "son");
test.get(82, "jung");
test.get(101, "seo");
test.get(109, "sad");
'자료구조' 카테고리의 다른 글
힙 정렬(Heap Sort) (0) | 2020.07.10 |
---|---|
큐(Queue) 스택(Stack) (0) | 2020.07.09 |
병합 정렬(Merge Sort) (0) | 2020.07.07 |
빠른 정렬(Quick Sort) (0) | 2020.07.03 |
삽입 정렬(Insertion Sort) (0) | 2020.07.02 |