source of hsearch_r 可以在网上找到。
如果键在表中,则函数在检查操作之前返回找到的条目,这意味着添加现有键的行为就像找到它一样。 (您可以在调用hsearch(ADD) 后覆盖“found”结构的值并覆盖旧值。)
该实现不适合元素删除。它维护一个桶数组。哈希冲突通过寻找另一个空桶来处理,因此桶索引不一定等于哈希码。当你插入两个哈希码相同的值时,第二个会得到这样一个哈希码不是桶索引的桶。
当您现在删除第一项然后尝试查找第二项时,将找不到它,因为仅当哈希码为桶索引的“最佳”桶已满时才考虑“其他”桶。
除了不更新的重新添加和缺少的删除选项之外,hsearch_r 还有其他限制。例如,条目的最大数量必须预先估计并且以后不能更改。我认为hsearch_r 旨在作为有限范围应用程序的快速哈希表。使用另一个更通用的哈希表实现可能会更好。
或者,您可以使用表示“不存在”的默认数据参数。 entry->data 的类型是void *,所以NULL 是一个显而易见的选择。以下数据是对手册页示例的修改,其中包装函数的语法比hsearch_r 更自然:
#include <stdio.h>
#include <stdlib.h>
#define _GNU_SOURCE
#define __USE_GNU
#include <search.h>
#define NIL (-1L)
void hadd(struct hsearch_data *tab, char *key, long value)
{
ENTRY item = {key, (void *) value};
ENTRY *pitem = &item;
if (hsearch_r(item, ENTER, &pitem, tab)) {
pitem->data = (void *) value;
}
}
void hdelete(struct hsearch_data *tab, char *key)
{
ENTRY item = {key};
ENTRY *pitem = &item;
if (hsearch_r(item, FIND, &pitem, tab)) {
pitem->data = (void *) NIL;
}
}
long hfind(struct hsearch_data *tab, char *key)
{
ENTRY item = {key};
ENTRY *pitem = &item;
if (hsearch_r(item, FIND, &pitem, tab)) {
return (long) pitem->data;
}
return NIL;
}
int main()
{
char *data[] = {
"apple", "pear", "cherry", "kiwi",
"orange", "plum", "pomegranate", NULL
};
char **p = data;
struct hsearch_data tab = {0};
int i;
hcreate_r(10, &tab);
for (i = 0; i < 5; i++) hadd(&tab, data[i], i + 1L);
hdelete(&tab, "pear");
hadd(&tab, "cherry", 144);
while (*p) {
long value = hfind(&tab, *p);
if (value == NIL) {
printf("%s: NIL\n", *p);
} else {
printf("%s: %ld\n", *p, value);
}
p++;
}
hdestroy_r(&tab);
return 0;
}
注意:如果您使用 ponters 作为数据并且哈希表拥有该数据,您必须 free 销毁数据,但在覆盖现有值时也是如此。