如何从hsearch中删除元素
我正在使用GNUC库提供的hsearch_r函数 我看到,虽然我可以使用hsearch\r将元素添加到哈希表中,并将操作作为ENTER传递,但我看不到从哈希表中删除元素或条目的方法 有人知道为什么会这样吗 我可以执行以下操作来实现我的删除功能 我首先使用hsearch\r搜索它,操作为FIND。一旦我得到一个指向hash_元素的指针,我就会释放它。这样行吗?如果我只能添加元素并搜索它们,那么散列库有什么用呢。为什么不提供删除例程 我试着在谷歌上搜索H搜索库的源代码,但找不到。有人能给我指一下吗 编辑: 我还看到,如果我用action ADD调用hsearch\r两次,那么它既不会抛出错误,也不会用新值更新哈希。这很奇怪。这意味着hsearch在内部没有实现替换功能,我们必须自己进行替换,即首先进行搜索,然后如果存在,则删除第一个条目,然后添加一个新条目。但是要做到这一点,我们需要从散列中删除一个元素,我无法删除。可以在线找到 如果键在表中,则函数在检查操作之前返回找到的条目,这意味着添加现有键的行为类似于查找它。(您可以在调用如何从hsearch中删除元素,c,search,hash,gnu,C,Search,Hash,Gnu,我正在使用GNUC库提供的hsearch_r函数 我看到,虽然我可以使用hsearch\r将元素添加到哈希表中,并将操作作为ENTER传递,但我看不到从哈希表中删除元素或条目的方法 有人知道为什么会这样吗 我可以执行以下操作来实现我的删除功能 我首先使用hsearch\r搜索它,操作为FIND。一旦我得到一个指向hash_元素的指针,我就会释放它。这样行吗?如果我只能添加元素并搜索它们,那么散列库有什么用呢。为什么不提供删除例程 我试着在谷歌上搜索H搜索库的源代码,但找不到。有人能给我指一下吗
hsearch(ADD)
后覆盖“found”结构的值,并覆盖旧值。)
该实现不适合删除元素。它维护一个bucket数组。哈希冲突是通过查找另一个空bucket来处理的,因此bucket索引不一定等于哈希代码。当您插入两个具有相同哈希代码的值时,第二个值将得到这样一个bucket,其中哈希代码不是bucket索引
当您现在删除第一项,然后尝试查找第二项时,将找不到该项,因为只有当哈希代码为bucket索引的“最佳”bucket已满时,才会考虑“其他”bucket
除了不更新的重新添加和缺少的删除选项外,hsearch\r
还有其他限制。例如,条目的最大数量必须事先估计,以后不能更改。我认为,hsearch\u 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;
}
#包括
#包括
#定义GNU源
#定义、使用
#包括
#定义零(-1L)
void hadd(结构hsearch_数据*选项卡,字符*键,长值)
{
条目项={key,(void*)value};
条目*pitem=&item;
if(hsearch_r(项目、输入和项目、选项卡)){
pitem->data=(void*)值;
}
}
void hdelete(结构搜索数据*选项卡,字符*键)
{
条目项={key};
条目*pitem=&item;
if(hsearch_r(项目、查找和项目、选项卡)){
pitem->data=(void*)无;
}
}
长hfind(结构hsearch_数据*选项卡,字符*键)
{
条目项={key};
条目*pitem=&item;
if(hsearch_r(项目、查找和项目、选项卡)){
返回(长)pitem->数据;
}
返回零;
}
int main()
{
字符*数据[]={
“苹果”、“梨”、“樱桃”、“猕猴桃”,
“橙子”、“李子”、“石榴”,无效
};
char**p=数据;
struct hsearch_data tab={0};
int i;
hcreate_r(10,&tab);
对于(i=0;i<5;i++)hadd(&tab,数据[i],i+1L);
hdelete(&tab,“pear”);
hadd(&tab,“cherry”,144);
而(*p){
长值=hfind(&tab,*p);
如果(值==NIL){
printf(“%s:NIL\n”,*p);
}否则{
printf(“%s:%ld\n”,*p,值);
}
p++;
}
hdestroy_r(&tab);
返回0;
}
注意:如果您使用ponters作为数据,并且哈希表拥有该数据,则必须
释放销毁时的数据,但也必须在覆盖现有值时释放该数据。@M Oehm,hsearch\u r
的第三个参数是应包含返回值的结构,对吗?那么,为什么要将其初始化为&项?附言:我是个新手,尝试使用hsearch_r@venkrao:无需初始化pitem
;您可以传递未初始化指针的地址,因为它将被覆盖。因此,&item
的初始化是令人困惑的,但却是有害的。如果应该初始化pitem
,更好的值可能是NULL
@M Oehm,谢谢。我在代码中观察到这种奇怪的行为,hsearch\u r
能够将元素输入哈希表。但是,当我尝试查找时,搜索失败。通过对一些print语句进行更多的调试,我意识到只有上次插入的元素保留在哈希表中。其他的没有,或者只是被覆盖了。我发现很难理解为什么只有一个元素(为什么会被覆盖),我想知道您是否见过类似的行为,希望我能很好地解释这个问题。@venkrao:没有代码就很难找到。为什么不在这里问个问题呢?检查事项:ENTER
操作是否表示成功?这张桌子够大吗?据我所知,它不能生长。是否更新输入结构的键?您可能无意中用相同的键覆盖了该项。@M Oehm,是的,ENTER
表示成功。这张桌子足够大了。我更新了结构的键,是的。我正在插入新元素,而不是覆盖。是的,我可能遗漏了什么。我张贴