IT 프로그래밍/알고리즘
[알고리즘] 해슁
기술1
2025. 6. 25. 15:14
Chaining
#include <iostream>
#include <list>
#include <vector>
using namespace std;
class HashTable {
int size;
vector<list<int>> table;
public:
HashTable(int m) : size(m), table(m) {}
int hash(int key) {
return key % size;
}
void insert(int key) {
int idx = hash(key);
table[idx].push_front(key); // 삽입은 맨 앞에
}
bool search(int key) {
int idx = hash(key);
for (int val : table[idx])
if (val == key) return true;
return false;
}
void remove(int key) {
int idx = hash(key);
table[idx].remove(key);
}
};
Open Addressing
class LinearProbingHash {
int size;
vector<int> table;
public:
LinearProbingHash(int m) : size(m), table(m, -1) {}
int hash(int key) {
return key % size;
}
void insert(int key) {
int idx = hash(key);
while (table[idx] != -1)
idx = (idx + 1) % size;
table[idx] = key;
}
bool search(int key) {
int idx = hash(key);
int start = idx;
while (table[idx] != -1) {
if (table[idx] == key) return true;
idx = (idx + 1) % size;
if (idx == start) break; // 무한루프 방지
}
return false;
}
void remove(int key) {
int idx = hash(key);
while (table[idx] != -1) {
if (table[idx] == key) {
table[idx] = -2; // 삭제된 자리 표시
return;
}
idx = (idx + 1) % size;
}
}
};
Linear probing
Quadratic Probing
void insertQuadratic(vector<int>& table, int key, int m) {
int idx = key % m;
int i = 0;
while (table[(idx + i*i) % m] != -1) i++;
table[(idx + i*i) % m] = key;
}
Double Hashing
int h1(int k, int m) { return k % m; }
int h2(int k) { return 1 + (k % 11); } // m과 서로소
void insertDoubleHash(vector<int>& table, int key, int m) {
int i = 0;
while (true) {
int idx = (h1(key, m) + i * h2(key)) % m;
if (table[idx] == -1) {
table[idx] = key;
break;
}
i++;
}
}
Multiplication 해시 함수
int hashMultiplication(int k, int m) {
double A = 0.6180339887; // (sqrt(5) - 1)/2, Knuth 제안
double frac = fmod(k * A, 1.0); // 소수 부분만
return int(m * frac);
}
전체 코드
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <string>
#include <cmath>
using namespace std;
#define DELETED -2 // 삭제된 슬롯을 표시하기 위한 특별한 값
//----------------------------------
// Division 방식 해시 함수: key를 테이블 크기로 나눈 나머지
int hash_division(int key, int m) {
return key % m;
}
// Multiplication 방식 해시 함수: Knuth 제안 방식
int hash_multiplication(int key, int m) {
double A = 0.6180339887; // (sqrt(5) - 1) / 2
double frac = fmod(key * A, 1.0);
return int(m * frac);
}
// 문자열 해시 함수 (Java 스타일): 31진법을 사용한 누적 해싱
int hash_string_javaStyle(const string& s) {
int hash = 0;
for (char c : s)
hash = c + (31 * hash);
return hash;
}
//----------------------------------
// Chaining 방식 해시 테이블 클래스
class HashTable_Chain {
int size;
vector<list<int>> table;
public:
HashTable_Chain(int m) : size(m), table(m) {}
void insert(int key) {
int idx = hash_division(key, size);
table[idx].push_front(key); // 리스트 맨 앞에 삽입
}
bool search(int key) {
int idx = hash_division(key, size);
for (int val : table[idx])
if (val == key) return true;
return false;
}
void remove(int key) {
int idx = hash_division(key, size);
table[idx].remove(key); // 연결 리스트에서 제거
}
};
//----------------------------------
// Linear Probing 방식 해시 테이블 클래스
class HashTable_LinearProbing {
int size;
vector<int> table;
public:
HashTable_LinearProbing(int m) : size(m), table(m, -1) {}
int hash(int key) { return key % size; }
void insert(int key) {
int idx = hash(key);
while (table[idx] != -1 && table[idx] != DELETED)
idx = (idx + 1) % size;
table[idx] = key;
}
bool search(int key) {
int idx = hash(key);
int start = idx;
while (table[idx] != -1) {
if (table[idx] == key) return true;
idx = (idx + 1) % size;
if (idx == start) break;
}
return false;
}
void remove(int key) {
int idx = hash(key);
while (table[idx] != -1) {
if (table[idx] == key) {
table[idx] = DELETED;
return;
}
idx = (idx + 1) % size;
}
}
};
//----------------------------------
// Quadratic Probing 방식 해시 테이블 클래스
class HashTable_QuadraticProbing {
int size;
vector<int> table;
public:
HashTable_QuadraticProbing(int m) : size(m), table(m, -1) {}
void insert(int key) {
int i = 0;
int idx;
do {
idx = (key % size + i * i) % size;
if (table[idx] == -1 || table[idx] == DELETED) {
table[idx] = key;
return;
}
i++;
} while (i < size);
}
bool search(int key) {
int i = 0;
int idx;
do {
idx = (key % size + i * i) % size;
if (table[idx] == key) return true;
if (table[idx] == -1) return false;
i++;
} while (i < size);
return false;
}
};
//----------------------------------
// Double Hashing 방식 해시 테이블 클래스
class HashTable_DoubleHashing {
int size;
vector<int> table;
int h1(int key) { return key % size; }
int h2(int key) { return 1 + (key % (size - 2)); } // size와 서로소 필요
public:
HashTable_DoubleHashing(int m) : size(m), table(m, -1) {}
void insert(int key) {
int i = 0;
int idx;
while (i < size) {
idx = (h1(key) + i * h2(key)) % size;
if (table[idx] == -1 || table[idx] == DELETED) {
table[idx] = key;
return;
}
i++;
}
}
bool search(int key) {
int i = 0;
int idx;
while (i < size) {
idx = (h1(key) + i * h2(key)) % size;
if (table[idx] == key) return true;
if (table[idx] == -1) return false;
i++;
}
return false;
}
};
//----------------------------------
// 메인 함수: input.txt로부터 키 읽어오기
int main() {
ifstream inFile("input.txt");
if (!inFile) {
cerr << "파일을 열 수 없습니다." << endl;
return 1;
}
const int tableSize = 11; // 해시 테이블 크기
HashTable_Chain chain(tableSize);
HashTable_LinearProbing linear(tableSize);
HashTable_QuadraticProbing quad(tableSize);
HashTable_DoubleHashing dbl(tableSize);
int key;
cout << "파일로부터 키를 읽어와 삽입 중...\n";
while (inFile >> key) {
chain.insert(key);
linear.insert(key);
quad.insert(key);
dbl.insert(key);
}
// 예시: 검색 테스트
int target = 27;
cout << "\n--- 검색 결과 (key = " << target << ") ---\n";
cout << "[Chaining] " << (chain.search(target) ? "찾음" : "없음") << "\n";
cout << "[Linear Probing] " << (linear.search(target) ? "찾음" : "없음") << "\n";
cout << "[Quadratic Probing] " << (quad.search(target) ? "찾음" : "없음") << "\n";
cout << "[Double Hashing] " << (dbl.search(target) ? "찾음" : "없음") << "\n";
return 0;
}