为什么需要哈希表? 数组和链表的局限性 在C语言中,我们通常使用数组或链表存储数据:
1 2 3 4 5 6 7 8 int array [100 ];struct Node { int data; struct Node * next ; }*LinkList;
哈希表的优势 哈希表结合了两者的优点:
哈希表基本原理 核心思想: 键(key) → 哈希函数 → 索引(index) → 存储值(value)
for example
1 2 3 4 5 6 7 8 9 10 11 12 +----------------+ | 索引 | 值 | +----------------+ | 0 | 空 | | 1 | 空 | | ... | ... | | 5 | key=25 | ← 25 存储在这里 | ... | ... | +----------------+
自己实现简单哈希表 基础结构 1 2 3 4 5 6 7 8 9 10 11 12 13 #define TABLE_SIZE 1000 struct HashNode { int key; int value; struct HashNode * next ; }; struct HashTable { struct HashNode * table [TABLE_SIZE ]; };
基本操作 哈希函数 插入 查找
1 2 3 int hashFunction (int key) { return key % TABLE_SIZE; }
1 2 3 4 5 6 7 8 9 void insert (struct HashTable* hashtable, int key, int value) { int index = hashFunction(key); struct HashNode * newNode = malloc (sizeof (struct HashNode)); newNode->key = key; newNode->value = value; newNode->next = hashtable->table[index]; hashtable->table[index] = newNode; }
1 2 3 4 5 6 7 8 9 10 11 int search (struct HashTable* hashtable, int key) { int index = hashFunction(key); struct HashNode * current = hashtable->table[index]; while (current) { if (current->key == key) { return current->value; } current = current->next; } return -1 ; }
uthash库:C语言哈希表终极解决方案 头文件 uthash 是C语言的一个开源哈希表库,只有头文件,使用非常方便。
只需下载uthash.h头文件 ,放入项目即可。
📥 下载说明 :点击链接后如果文件直接打开,请右键链接选择”另存为”。
s
### 定义结构体
定义结构体,确定好键值类型
1 2 3 4 5 6 struct hashTable { int key; char name[20 ]; UT_hash_handle hh; };
uthash宏 初始化 插入元素 查找元素 删除元素 遍历所有元素 获取元素数量 排序
1 struct hashTable * hashtable = NULL ;
添加元素宏 1 2 3 HASH_ADD_INT(head, keyfield, item); HASH_ADD_STR(head, keyfield, item); HASH_ADD_PTR(head, keyfield, item);
1 2 3 4 5 6 void insert (int k, char *name) { struct hashTable *item = malloc (sizeof (struct hashTable)); item->key = k; strcpy (item->name, name); HASH_ADD_INT(hashtable, key, item); }
查找元素宏 1 2 3 HASH_FIND_INT(head, keyptr, out); HASH_FIND_STR(head, keyptr, out); HASH_FIND_PTR(head, keyptr, out);
1 2 3 4 5 struct hashTable* find (int key) { struct hashTable * out ; HASH_FIND_INT(hashtable, &key, out); return out; }
删除元素宏 1 2 3 4 5 6 7 HASH_DEL(users, user_to_delete); HASH_DELETE(hh, users, user_to_delete); free (user_to_delete); HASH_CLEAR(hh, hashtable);
1 2 3 4 void delete (struct hashTable *s) { HASH_DEL(hashtable, s); free (s); }
遍历宏 1 2 3 4 5 6 7 8 9 10 11 User *current, *tmp; HASH_ITER(hh, hashtable, current, tmp) { printf ("ID: %d, Name: %s\n" , current->id, current->name); } for (current = hashtable; current != NULL ; current = current->hh.next) { }
1 2 3 4 5 6 void print_all () { struct hashTable *s , *tmp ; HASH_ITER(hh, hashtable, s, tmp) { printf ("ID: %d, Name: %s\n" , s->id, s->name); } }
1 2 3 int count () { return HASH_COUNT(hashtable); }
1 2 3 4 5 HASH_SORT(hashtable, compare_func); int compare_func (struct hashTable *a, struct hashTable *b) { return strcmp (a->name, b->name); }