【问题标题】:how to search using double hash in c如何在c中使用双哈希进行搜索
【发布时间】:2015-07-20 02:34:41
【问题描述】:

我有一个服务器来接收来自多个客户端的请求。我已经用线程做到了这一点。我想在哈希表中插入一些用户名和密码。为此,我使用双哈希方法。已成功插入。但是我想知道当用户输入用户名时,我需要在哈希表上搜索这个用户名是否已经存在。但我现在做不到。我知道像使用散列这样的概念。通过用户名使用 hashfunction1 获取索引并像这样使用双哈希。但是我怎样才能写出那个代码呢?

我的代码:

int HashFunc1 (char *key,int size)
{
    int i = 0,value = 0;

    for(i = 0 ; key[i] != '\0'; i++)
    {
            value += ( key[i] + ( i + 1 ) );
    }
    return value % size;
}

int HashFunc2 (char *key,int size)
{
    int i = 0,value = 0;

    for(i = 0; key[i] != '\0'; i++)
    {
            value += ( key[i] + ( i + 1 ) );
    }

    return (value * size - 1) % size;
}

int Findindex(char *key,struct HashTable **htable)
{

    int     hashVal = 0,
            stepSize = 0;

    hashVal = HashFunc1(key, (*htable)->size);
    stepSize= HashFunc2(key, (*htable)->size);

    /*to avoid collisions)*/
    while ( (*htable)->table[hashVal].username != NULL)
    {
            /*double hahsing process*/
            hashVal = hashVal + stepSize;
            hashVal = hashVal % (*htable)->size;
    }

    return hashVal;

}

int insert_to_hashtable(char *key,char *password,struct HashTable **htable)
{
           int      pos = 0;

    /*find the index to insert new user datas*/
    pos = Findindex(key,htable);

   //code to insert to coresponding data if this empty 
}

如何编写代码以使用 C 中的哈希表中的双重哈希来搜索已经存在的用户名?我认为遍历整个哈希表不是一个好习惯..是吗?

【问题讨论】:

  • 当我使用用户名搜索特定索引时,但问题是双重哈希。因为我在最初插入用户名时使用双重哈希方法来查找空缺位置。再次搜索后,我遍历整个哈希表。是吗?

标签: c pointers hash hashtable double-hashing


【解决方案1】:

您的哈希表大小固定为 S,因此您最多可以输入 S 个元素。

哈希码 H1 和 H2 的双重哈希的思想是:如果在 H1 位置已经有一个条目,则将哈希宽度遍历 H2 步长。大小 S 是素数。这意味着除了 H2 = 0 之外的任何步幅 H2

当然,如果你找到一个空槽,你就拿走它。在一个稀疏的散列中,你通常只需要从原始值走几步就可以找到一个空槽。

您的哈希填充得越多,关键字搜索的效率就越低。一种解决方案是跟踪元素的数量并将散列调整为更大的大小,例如,当超过 75% 的条目被占用时。当然,新尺寸也必须是素数。

还要注意您的代码中的这些问题:您可能会为步长生成一个 0 的哈希值,如果您的哈希表已满,您对空槽的搜索将无限循环。也没有必要通过引用传递哈希表,因为您永远不会更改指针本身,只会更改其结构成员。你甚至可以同时制作keyhtable const

所以:

int Findindex(const char *key, const struct HashTable *htable)
{    
    int hashVal, stepSize, startVal;

    hashVal = HashFunc1(key, htable->size);
    if (htable->table[hashVal].username == NULL) return hashVal;

    startVal = hashVal;
    stepSize = HashFunc2(key, (*htable)->size - 1) + 1;

    do  {
        hashVal = (hashVal + stepSize) % htable->size;
        if (hashVal == startVal) return -1;
    } while (htable->table[hashVal].username);

    return hashVal;
}

此代码返回一个特殊值 -1,表示哈希表中没有任何空槽。

如果您想查找用户名,请使用相同的策略。在这里,您必须额外比较每个节点的密钥,因为不同的密钥可能共享相同的哈希码。如果您找到一个空槽,则该条目不在表中。

此函数返回一个指向与键关联的用户数据(我将其类型命名为struct data;您不显示哈希表结构的定义)的指针,如果用户不能,则返回NULL被发现:

struct data *FindKey(const char *key, const struct HashTable *htable)
{    
    int hashVal, stepSize, startVal;

    hashVal = HashFunc1(key, htable->size);
    if (htable->table[hashVal].username == NULL) return NULL;
    if (strcmp(htable->table[hashval].username, key) == 0) {
        return &htable->table[hashVal];
    }

    startVal = hashVal;
    stepSize = HashFunc2(key, (*htable)->size - 1) + 1;

    for(;;)  {
        hashVal = (hashVal + stepSize) % htable->size;
        if (hashVal == startVal) return NULL;
        if (htable->table[hashVal].username == NULL) return NULL;
        if (strcmp(htable->table[hashval].username, key) == 0) {
            return &htable->table[hashVal];
        }
    }

    return NULL;
}

警告:我没有测试过这段代码,但我希望你了解基本的工作原理。

【讨论】:

  • 插入到哈希表没问题..插入后如何搜索特定用户名?使用双重哈希..我不想搜索整个哈希表
  • 我想你误解了哈希表的用途:哈希码意味着你开始寻找最可能的地方。当它被另一个项目(使用相同的哈希码以您的表大小取模)时,开始查看下一个可能的位置。如果您的表已满且找不到匹配项,您只会查看整个表。
  • 顺便说一下,您可能想研究一下哈希函数。乍一看,您的函数似乎不会产生均匀分布的哈希值。错误的哈希函数也会导致无效的查找。
  • 好的,我接受你的回答......我明白了......但是你能建议一些代码来搜索是否存在的用户名......我如何从哈希表中搜索
  • 查找与查找空槽相同,只是您将密钥与用户名进行比较。 (我已将其添加到我的帖子中,但代码未经测试。)
猜你喜欢
  • 2014-04-07
  • 2011-07-16
  • 1970-01-01
  • 2013-04-06
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 2020-01-30
相关资源
最近更新 更多