Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从hsearch中删除元素_C_Search_Hash_Gnu - Fatal编程技术网

如何从hsearch中删除元素

如何从hsearch中删除元素,c,search,hash,gnu,C,Search,Hash,Gnu,我正在使用GNUC库提供的hsearch_r函数 我看到,虽然我可以使用hsearch\r将元素添加到哈希表中,并将操作作为ENTER传递,但我看不到从哈希表中删除元素或条目的方法 有人知道为什么会这样吗 我可以执行以下操作来实现我的删除功能 我首先使用hsearch\r搜索它,操作为FIND。一旦我得到一个指向hash_元素的指针,我就会释放它。这样行吗?如果我只能添加元素并搜索它们,那么散列库有什么用呢。为什么不提供删除例程 我试着在谷歌上搜索H搜索库的源代码,但找不到。有人能给我指一下吗

我正在使用GNUC库提供的hsearch_r函数

我看到,虽然我可以使用hsearch\r将元素添加到哈希表中,并将操作作为ENTER传递,但我看不到从哈希表中删除元素或条目的方法

有人知道为什么会这样吗

我可以执行以下操作来实现我的删除功能

我首先使用hsearch\r搜索它,操作为FIND。一旦我得到一个指向hash_元素的指针,我就会释放它。这样行吗?如果我只能添加元素并搜索它们,那么散列库有什么用呢。为什么不提供删除例程

我试着在谷歌上搜索H搜索库的源代码,但找不到。有人能给我指一下吗

编辑:

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

可以在线找到

如果键在表中,则函数在检查操作之前返回找到的条目,这意味着添加现有键的行为类似于查找它。(您可以在调用
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
表示成功。这张桌子足够大了。我更新了结构的键,是的。我正在插入新元素,而不是覆盖。是的,我可能遗漏了什么。我张贴