[Coding Test] Hash 구현 (2)
이전 함수에서 remove()
함수를 추가했다. Double Linked List 형태로 노드를 구현해 삭제 시 용이하게 만들었다.
#define TableSize 50000
#define MaxKeySize 11
struct Node {
int data;
char key[MaxKeySize];
Node* child;
Node* parent;
};
void mstrcpy(char* dest, const char* src) {
int idx = 0;
while ((dest[idx] = src[idx]) != '\0') ++idx;
}
int mstrcmp(char* str1, char* str2) {
int idx = 0;
while (str1[idx] != '\0' && str1[idx] == str2[idx]) ++idx;
return str1[idx] == str2[idx] ? true : false;
}
struct Hash {
int hashNum;
Node node[100'005];
Node* hashTable[TableSize];
void init() {
hashNum = 0;
for (int i = 0; i < 100'005; i++) {
node[i].child = nullptr;
node[i].parent = nullptr;
}
for (int i = 0; i < TableSize; i++)
hashTable[i] = nullptr;
}
unsigned long getHash(char* str) {
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = (hash << 5) + hash + c;
return hash % TableSize;
}
void add(char* key, int data) {
Node* n = &node[hashNum++];
unsigned long hKey = getHash(key);
// Key, Value 삽입
mstrcpy(n->key, key);
n->data = data;
// 충돌 조치
Node* prev = hashTable[hKey];
n->child = prev;
if(prev != nullptr)
prev->parent = n;
hashTable[hKey] = n;
}
int get(char* key) {
unsigned long hKey = getHash(key);
for (Node* n = hashTable[hKey]; n != nullptr; n = n->child) {
// Key 값 일치하면 반환
if (mstrcmp(n->key, key)) return n->data;
}
return -1;
}
int remove(char* key) {
unsigned long hKey = getHash(key);
int data = -1;
for (Node* n = hashTable[hKey]; n != nullptr; n = n->child) {
// Key 값 일치하지 않으면 Pass
if (!mstrcmp(n->key, key)) continue;
// 삭제하는 데이터
data = n->data;
if (n->parent == nullptr) {
// 삭제하는 데이터의 parent 노드가 존재하지 않는 경우
hashTable[hKey] = n->child;
if (n->child != nullptr) n->child->parent = nullptr;
break;
}
else {
// 삭제하는 데이터의 parent 노드가 존재하는 경우
n->parent->child = n->child;
if (n->child != nullptr) {
n->child->parent = n->parent;
}
break;
}
}
return data;
}
};
Hash cHash;
Leave a comment