#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/**----------------------------------------哈希表节点-----------------------------------**/
typedef struct _Node {
void * key;
void * value;
int hash;
struct _Node * next;
} Node;
/**----------------------------------------哈希表节点结束-------------------------------**/
/**-------------------------------------------------------------------------------------**/
/**-------------------------------------------------------------------------------------**/
/**-------------------------------------------------------------------------------------**/
/**----------------------------------------哈希表---------------------------------------**/
typedef struct _HashTable {
int cnt;
int tableLength;
Node ** tables;
// simple Methord
void (*put)(struct _HashTable *this, const void *key, void* value);
void*(*get)(struct _HashTable *this, const void *key);
void (*destroy)(struct _HashTable *this);
void (*resize)(struct _HashTable *this);
// help Methord 需要声明
Node* (*Create_Node)(const void * key, void* value, int hash);
void (*Destory_Node)(Node * node);
int (*Compute_Hash)(const void * key);
int (*Keys_Equal)(const void * s, const void * t);
} HashTable;
void put(HashTable *this, const void *key, void * value) {
int hash = this -> Compute_Hash(key);
int pos = hash & (this -> tableLength - 1);
Node * head = this -> tables[pos];
while(head != NULL) {
if (this -> Keys_Equal(key, head -> key) == 0) {
head -> value = value;
return;
}
head = head -> next;
}
if (this -> cnt >= (int)(this -> tableLength * 0.75)) {
this -> resize(this);
pos = hash & (this -> tableLength - 1);
}
this -> cnt = this -> cnt + 1;
Node * in = this -> Create_Node(key, value, hash);
in -> next = this -> tables[pos];
this -> tables[pos] = in;
}
void* get(HashTable *this, const void *key) {
int hash = this -> Compute_Hash(key);
int pos = hash & (this -> tableLength - 1);
Node * head = this -> tables[pos];
while(head != NULL) {
if (this -> Keys_Equal(key, head -> key) == 0) {
return head -> value;
}
head = head -> next;
}
return NULL;
}
void resize(HashTable *this) {
int tableLength = this -> tableLength << 1;
int i;
Node * tmp;
Node ** tables = (Node **)malloc(sizeof(Node *) * tableLength);
memset(tables, 0, sizeof(Node *) * tableLength);
// 拷贝 速度
for(i = 0; i < this -> tableLength; ++i) {
Node * head = this -> tables[i];
while(head != NULL) {
tmp = head;
head = head -> next;
int pos = tmp -> hash & (tableLength - 1 );
tmp -> next = tables[pos];
tables[pos] = tmp;
}
}
// 防止被别人申请到 但是不是0,其实不操作也没事
memset(this -> tables, 0, sizeof(Node *) * this -> tableLength);
free(this -> tables);
this -> tables = tables;
this -> tableLength = tableLength;
}
// 最后写 这是 C/C++ 语言最恶心的地方,切记
void destroy(HashTable *this) {
int i = this -> tableLength;
Node * next;
for(i = 0; i < this -> tableLength; ++i) {
Node * now = this -> tables[i];
while(now != NULL) {
next = now -> next;
this -> Destory_Node(now);
now = next;
}
}
free(this -> tables);
}
/**
* @param Create_Node 创建hash节点的函数
* @param Compute_Hash 计算hash节点key 的hashCode 的函数
* @param Keys_Equal 判断hash节点key 相等的函数,判断 == 0 代表相等
* @param Destory_Node 销毁hash节点的函数:
* Description: 初始化 hash表
* 之所以 需要填写 这么多的函数,主要是因为,HashNode 的key, value 在是指针的情况下,需要确定
* (1):初始化Node: 是拷贝模式,还是 直接使用模式
* (2):销毁 Node: 是否需要 去 free 掉
* 所以 需要 手动的传递这么多函数
* 一个 字符串作为 key
*/
HashTable * initTable(Node* (*Create_Node)(const void * key, void * value, int hash),
int (*Compute_Hash)(const void * key),
int (*Keys_Equal)(const void *s, const void *t),
void (*Destory_Node)(Node * node)) {
HashTable * ans = (HashTable*)malloc(sizeof(HashTable));
ans -> cnt = 0 ;
ans -> tableLength = 8;
ans -> put = put;
ans -> get = get;
ans -> destroy = destroy;
ans -> resize = resize;
ans -> Create_Node = Create_Node;
ans -> Compute_Hash = Compute_Hash;
ans -> Keys_Equal = Keys_Equal;
ans -> Destory_Node = Destory_Node;
Node ** tables = (Node **)malloc(sizeof(Node *) * ans -> tableLength);
memset(tables, 0, sizeof(Node *) * ans -> tableLength);
ans -> tables = tables;
return ans;
}
/**----------------------------------------哈希表结束---------------------------------------**/
/*
下面三个函数,主要实现
key(type = "字符串", mode = "拷贝模式")
value(type = "int", mode = "拷贝模式")
*/
Node * initNode(const void * _key, void * _value, int hash){
Node * in = (Node *)malloc(sizeof(Node));
char * key = (char *)_key;
int kLen = strlen(key);
char * copy = (char *)malloc(sizeof(char) * (kLen + 1));
strcpy(copy, key);
in -> key = (void *) copy;
int * value = (int *)malloc(sizeof(int));
*value = *((int*)_value);
in -> value = value;
in -> hash = hash;
in -> next = NULL;
return in;
}
void destoryNode(Node * node) {
free(node -> key);
free(node -> value);
node -> key = node -> next = node -> value = NULL;
free(node);
}
int String_Hash_Code(const void * _ch) {
const char * ch = (const char *)_ch;
int i = 0, ans = 0;
for(i = 0 ; ch[i] != '\0'; ++i) {
ans = 31 * ans + ch[i];
}
return ans;
}
int stringEqual(const void * _s, const void * _t) {
return strcmp(_s, _t);
}
int main() {
HashTable* table = initTable(initNode, String_Hash_Code, stringEqual, destoryNode);
char a[20];
int value, n;
scanf("%d", &n);
for(int w = 0; w < n; ++w) {
scanf("%s %d", a, &value);
table -> put(table, a, &value);
}
printf("table size %d, length %d\n", table -> cnt, table -> tableLength);
printf("%s, %d\n", "1221", *(int*)table -> get(table, "1221"));
int* ans = (int*)table -> get(table, "12312");
printf("%s, %d\n", "12312", ans == NULL ? -1 : *ans);
table -> destroy(table);
free(table);
return 0;
}