int hashFunction(int key, int tableSize) {
return key % tableSize;
}
int CHT_Hash(char* Key, int KeyLength, int TableSize) {
int hashValue = 0;
for (int i = 0; i < KeyLength; i++)
{
hashValue = (hashValue << 3) + Key[i]; // 놀게되는 앞 3bit 이용하도록
}
return hashValue % TableSize; // tablesize를 넘는 index가 안나오도록 조치
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* KeyType;
typedef char* ValueType;
typedef struct tagNode
{
KeyType Key;
ValueType Value;
struct tagNode* Next;
} Node;
typedef struct tagSet
{
Node* Setinfo;
KeyType data;
} Set;
typedef Node* List;
typedef struct tagHashTable
{
int TableSize;
List* Table;
} HashTable;
HashTable* CHT_CreateHashTable(int TableSize);
void CHT_DestroyHashTable(HashTable* HT);
Node* CHT_CreateNode(KeyType Key, ValueType Value);
void CHT_DestroyNode(Node* TheNode);
void CHT_Set(HashTable* HT, KeyType Key, ValueType Value);
ValueType CHT_Get(HashTable* HT, KeyType Key);
int CHT_Hash(KeyType Key, int KeyLength, int TableSize);
HashTable* CHT_CreateHashTable(int TableSize)
{
HashTable* HT = (HashTable*)malloc(sizeof(HashTable));
HT->Table = (List*)malloc(sizeof(List) * TableSize); // List = Node* 이므로 Node*의 배열은 Node**가 가르켜야 한다.
memset(HT->Table, 0, sizeof(List) * TableSize); // 포인터에서는 NULL = 0
HT->TableSize = TableSize;
return HT;
}
void CHT_DestroyHashTable(HashTable* HT)
{
for (int i = 0; i < HT->TableSize; i++)
{
List L = HT->Table[i];
CHT_DestroyNode(L);
}
free(HT->Table);
free(HT);
}
Node* CHT_CreateNode(KeyType Key, ValueType Value)
{
Node* NewNode = (Node*)malloc(sizeof(Node));
NewNode->Key = (char*)malloc(sizeof(char) * (strlen(Key) + 1));
strcpy(NewNode->Key, Key);
NewNode->Value = (char*)malloc(sizeof(char) * (strlen(Value) + 1));
strcpy(NewNode->Value, Value);
NewNode->Next = NULL;
return NewNode;
}
void CHT_DestroyNode(Node* TheNode)
{
free(TheNode->Key);
free(TheNode->Value);
free(TheNode);
}
void CHT_Set(HashTable* HT, KeyType Key, ValueType Value) // 노드 삽입
{
int index = CHT_Hash(Key, strlen(Key), HT->TableSize);
Node* NewNode = CHT_CreateNode(Key, Value);
if (HT->Table[index] == NULL) // 충돌발생 X
{
HT->Table[index] = NewNode;
}
else // 충돌발생
{
List list = HT->Table[index];
HT->Table[index] = NewNode;
NewNode->Next = list;
printf("충돌발생 : Key(%s), address(%d)\n", Key, index);
}
}
ValueType CHT_Get(HashTable* HT, KeyType Key) // 다른방식으로 구현
{
int index = CHT_Hash(Key, strlen(Key), HT->TableSize);
List current = HT->Table[index];
while (1)
{
if (current == NULL)
{
break;
}
else if (strcmp(current->Key, Key) == 0)
{
break;
}
else
{
current = current->Next;
}
}
if (current != NULL)
{
return current->Value;
}
}
List CHT_GetList(HashTable* HT, KeyType Key) // 다른방식으로 구현
{
int index = CHT_Hash(Key, strlen(Key), HT->TableSize);
List current = HT->Table[index];
while (1)
{
if (current == NULL)
{
break;
}
else if (strcmp(current->Key, Key) == 0)
{
break;
}
else
{
current = current->Next;
}
}
if (current != NULL)
{
return current;
}
}
int CHT_Hash(KeyType Key, int KeyLength, int TableSize) {
int hashValue = 0;
for (int i = 0; i < KeyLength; i++)
{
hashValue = (hashValue << 3) + Key[i];
}
return hashValue % TableSize; // tablesize를 넘는 index가 안나오도록 조치
}
Set* makeSet(HashTable* HT, KeyType data) { // 집합 생성
Set* newSet = (Set*)malloc(sizeof(Set));
newSet->Setinfo = (Node*)malloc(sizeof(Node));
newSet->Setinfo->Key = data;
newSet->Setinfo->Value = data;
newSet->Setinfo->Next = NULL;
newSet->data = data;
CHT_Set(HT, data, data); // hash table에는 key = value인 상태로 등록
return newSet;
}
ValueType findSet(HashTable* HT, Set* targetSet) { // 집합이 어디에 속해있는지 찾기 : 집합의 data값을 key로했을때 value값
ValueType targetValue;
KeyType key = targetSet->Setinfo->Key;
while (1)
{
targetValue = CHT_Get(HT, key); // key == value인 값이 나올때 그 set이 Root set이다.
printf("%s -> ", targetValue);
if (targetValue == key)
{
break;
}
key = targetValue;
}
printf("\n");
return targetValue; // rootset의 value 반환
}
void unionSet(HashTable* HT, Set* set_1, Set* set_2) { // 상위 집합의 value를 하위 집합의 value로 업데이트하기
set_2->Setinfo = set_1->Setinfo;
ValueType Value_1 = CHT_Get(HT, set_1->Setinfo->Key);
List List_2 = CHT_GetList(HT, set_2->data);
List_2->Value = Value_1;
}
int main(void) {
HashTable* HT = CHT_CreateHashTable(12289);
Set* set_1 = makeSet(HT, "Han");
Set* set_2 = makeSet(HT, "Kim");
Set* set_3 = makeSet(HT, "Lee");
Set* set_4 = makeSet(HT, "Choi");
Set* set_5 = makeSet(HT, "Park");
//printf("set1 : %s == set2 : %s -> %d\n", findSet(HT, set_1), findSet(HT, set_2), findSet(HT, set_1) == findSet(HT, set_2));
//printf("set1 : %s == set3 : %s -> %d\n", findSet(HT, set_1), findSet(HT, set_3), findSet(HT, set_1) == findSet(HT, set_3));
unionSet(HT, set_1, set_3); // Lee를 Han으로
printf("set1 : %s == set3 : %s -> %d\n", findSet(HT, set_1), findSet(HT, set_3), findSet(HT, set_1) == findSet(HT, set_3));
unionSet(HT, set_2, set_1);
printf("set2 : %s == set3 : %s -> %d\n", findSet(HT, set_2), findSet(HT, set_3), findSet(HT, set_2) == findSet(HT, set_3));
unionSet(HT, set_5, set_2);
printf("set5 : %s == set3 : %s -> %d\n", findSet(HT, set_5), findSet(HT, set_3), findSet(HT, set_5) == findSet(HT, set_3));
printf("set5 : %s == set1 : %s -> %d\n", findSet(HT, set_5), findSet(HT, set_1), findSet(HT, set_5) == findSet(HT, set_1));
unionSet(HT, set_4, set_5);
printf("set4 : %s == set3 : %s -> %d\n", findSet(HT, set_4), findSet(HT, set_3), findSet(HT, set_4) == findSet(HT, set_3));
printf("%s\n", set_3->data);
printf("set1: %s\n", CHT_Get(HT, set_1->Setinfo->Key));
printf("set2: %s\n", CHT_Get(HT, set_2->Setinfo->Key));
printf("set3: %s\n", CHT_Get(HT, set_3->Setinfo->Key));
printf("set4: %s\n", CHT_Get(HT, set_4->Setinfo->Key));
printf("set5: %s\n", CHT_Get(HT, set_5->Setinfo->Key));
}
Han -> Han ->
Han -> Han ->
Han -> Han ->
Han -> Han ->
set1 : Han == set3 : Han -> 1
Kim -> Kim ->
Kim -> Kim ->
Kim -> Kim ->
Kim -> Kim ->
set2 : Kim == set3 : Kim -> 1
Park -> Park ->
Kim -> Park -> Park ->
Kim -> Park -> Park ->
Park -> Park ->
set5 : Park == set3 : Park -> 1
Park -> Park ->
Park -> Park ->
Park -> Park ->
Park -> Park ->
set5 : Park == set1 : Park -> 1
Choi -> Choi ->
Kim -> Park -> Choi -> Choi ->
Kim -> Park -> Choi -> Choi ->
Choi -> Choi ->
set4 : Choi == set3 : Choi -> 1
Lee
set1: Park
set2: Choi
set3: Kim
set4: Choi
set5: Choi
레드 블랙 트리 :
장점 : 리스트에 비해 빠른 시간에 탐색을 할 수 있다.
단점 : 여러 자료형에 대해 비교할 수 있는 비교자를 만들어야 함.
트리 규칙을 만족하는데에 연산이 필요
해쉬 테이블 :
장점: 충돌이 발생한 케이스에서 값을 찾아내는데 가장 빠른 시간이 걸림
단점: 해쉬 테이블을 이용하는데 막대한 공간이 필요
체이닝과 개방 주소법을 같이 사용할 경우 탐사 이동횟수를 덜 할 수 있다.다만 몇 번째 탐색부터 체이닝을 할 것인지 정하지 않는다면 탐사를 제대로 하기도 전에 체이닝 되어 탐색 효율이 떨어질 수 있다.