C语言 实现 HashTable
#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; }