如何从hsearch中删除元素

我正在使用GNU C库提供的hsearch_r函数。

我看到虽然我可以使用hsearch_r将元素添加到HASH表中并将操作作为ENTER传递,但我看不到从HASH表中删除元素或条目。

有人知道为什么会这样吗?

我可以执行以下操作来实现删除function。

我首先使用hsearch_r搜索它,其操作为FIND。 然后,一旦我得到一个指向hash_element的指针,然后我释放它。 那会有用吗? 如果我只能添加元素并搜索它们,那么哈希库有什么用处。 为什么不提供删除例程?

我试着用谷歌搜索hsearch库的源代码而无法找到它。 有人也能指出我的意思吗?

http://linux.die.net/man/3/hcreate_r

编辑:

我也看到,如果我用动作ADD调用hsearch_r两次,那么它既不会抛出错误,也不会使用新值更新散列。 这很奇怪。 这意味着内部hsearch不实现替换function,我们必须自己完成,即首先进行搜索,然后如果存在,则删除第一个条目,然后添加一个新条目。 但是要做到这一点,我们需要从哈希中删除一个元素,我无法做到。

hsearch_r的来源可以在网上找到。

如果键在表中,则函数在检查操作之前返回找到的条目,这意味着添加现有键的行为就像找到它一样。 (在调用hsearch(ADD)并覆盖旧值之后,您可以覆盖“found”结构的值。)

该实现不适合删除元素。 它维护着一系列桶。 通过查找另一个空桶来处理散列冲突,以便桶索引不一定等于散列码。 当您使用相同的哈希码插入两个值时,第二个将获得这样的桶,其中哈希码不是桶索引。

当您现在删除第一个项目然后尝试查找第二个项目时,将无法找到它,因为只有当哈希码为存储区索引的“最佳”存储区已满时才会考虑“其他”存储区。

除了不更新的重新添加和丢失的删除选项之外, hsearch_r还有其他限制。 例如,必须事先估计条目的最大nuber,并且以后不能更改。 我认为hsearch_r旨在作为有限范围应用程序的快速哈希表。 使用另一个更通用的哈希表实现可能会更好。

或者,您可以使用默认数据参数,表示“不存在”。 entry->data的类型是void * ,所以NULL是一个明显的选择。 以下数据是对包含函数的手册页示例的修改,这些函数具有比hsearch_r更自然的语法:

 #include  #include  #define _GNU_SOURCE #define __USE_GNU #include  #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数据,但也必须在覆盖现有值时free数据。