【问题标题】:Trying to understand hash table code in c++试图理解 C++ 中的哈希表代码
【发布时间】:2017-07-24 22:37:07
【问题描述】:

我正在学习哈希表,并在另一个网站上找到了此代码,但无法理解 Insert(int key, int value) 函数。 该功能运行良好,但我想知道是否有不需要的额外代码,或者我是否不完全理解它。

具体来说,函数末尾的else条件:

else
{
     entry->value = value;
 }

当我使用不同的参数调用该函数时,它似乎永远不会达到那个条件。这是其余的代码。

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstdio>
using namespace std;
const int TABLE_SIZE = 128;

class HashNode
{
public:
    int key;
    int value;
    HashNode* next;
    HashNode(int key, int value)
    {
        this->key = key;
        this->value = value;
        this->next = NULL;
    }
};

class HashMap
{
private:
    HashNode** htable;
    public:
    HashMap()
    {
        htable = new HashNode*[TABLE_SIZE];
        for (int i = 0; i < TABLE_SIZE; i++)
            htable[i] = NULL;
    }
    ~HashMap()
    {
        for (int i = 0; i < TABLE_SIZE; ++i)
        {
            HashNode* entry = htable[i];
            while (entry != NULL)
            {
                HashNode* prev = entry;
                entry = entry->next;
                delete prev;
            }
        }
        delete[] htable;
    }
    /*
     * Hash Function
     */
    int HashFunc(int key)
    {
        return key % TABLE_SIZE;
    }

    /*
     * Insert Element at a key
     */
    void Insert(int key, int value)
    {
        int hash_val = HashFunc(key);
        HashNode* prev = NULL;
        HashNode* entry = htable[hash_val];
        while (entry != NULL)
        {
            prev = entry;
            entry = entry->next;
        }
        if (entry == NULL)
        {
            entry = new HashNode(key, value);
            if (prev == NULL)
            {
                htable[hash_val] = entry;
            }
            else
            {
                prev->next = entry;
            }
        }
        else
        {
            entry->value = value;
        }
    }

    /* Search Element at a key
     */
    int Search(int key)
    {
        bool flag = false;
        int hash_val = HashFunc(key);
        HashNode* entry = htable[hash_val];
        while (entry != NULL)
        {
            if (entry->key == key)
            {
                cout << entry->value << " ";
                flag = true;
            }
            entry = entry->next;
        }
        if (!flag)
            return -1;
    }
};

int main()
{
    HashMap hash;
    hash.Insert(3, 7);
    hash.Search(3);
}

高度赞赏任何澄清。

谢谢

【问题讨论】:

  • 首先要做的是整理缩进。糟糕的缩进让代码更难解释。
  • 现在不碍事了,让我们来看看......
  • 这只是一段多余的代码。正如您所观察到的,由于循环,条目保证为空。如果 hash 和 key 都匹配,你确实设置了 value,但这在其他地方处理。

标签: c++ hash hashtable


【解决方案1】:
while (entry != NULL)

先于

if (entry == NULL) 

除非entryNULL,否则无法摆脱while (entry != NULL) 循环,保证else 的情况是不可能的。

我相信在while 循环内需要进行测试以查看密钥是否已经存在。

while (entry != NULL)
{
    if (entry->key == key)
    {
        break;
    }
    prev = entry;
    entry = entry->next;
}

题外话:查看此问题并回答有关如何简化代码的建议:Using pointers to remove item from singly-linked list

例子:

/*
 * Insert Element at a key
 */
void Insert(int key, int value)
{
    int hash_val = HashFunc(key);
    HashNode** nextPtr = &htable[hash_val]; // Get a pointer to next, not to the entry
    // with a pointer to next we can keep going from next to next without 
    // ever needing a previous.
    // pick up a whole bunch of extra dereferencing *nextPtr, but an 
    // optimizing compiler is great at dealing with that extra overhead.
    while ((*nextPtr) != NULL) // loop until found or end
    {
        if ((*nextPtr)->key == key) // found key already in list
        {
            (*nextPtr)->value = value; // set value for key
            return; // all done.
        }
        nextPtr = &(*nextPtr)->next; // keep looking
    }
    *nextPtr = new HashNode(key, value); // didn't find. Add new node to end.
}

附录:Search 仅在失败情况下返回。声明为返回值的函数必须始终返回一个值。

【讨论】:

  • 如果密钥已经在哈希表中,他们似乎打算跳出while循环,但忘记这样做了。
  • @interjay 很有可能。如果条目在哈希表中,我不确定他们的计划是什么。锁链还是拒绝插入?无论如何都会调整答案。如果不尝试解决方案,答案就不算多,是吗?
  • else 改变了现有条目的值,所以我想这就是意图。只需将&amp;&amp; entry-&gt;key != key 添加到while 条件即可。
  • 非常感谢。超快速反应。我还有一个关于搜索功能的问题。如果存在“与多个值的冲突”,我看不到 entry->value 如何输出多个值。它可以工作并使用相同的 key 输出多个值。但我只看到一个指针,它是可以取消引用 entry->value 的条目。看不到它如何在 entry->value 保存多个单独的值
  • @ldc57 据我所知,它只打印一个值(如果存在)。问题是,如果一个值存在,它不会像int Search(int key) 指定的那样返回int,从而导致一个无效的程序可以做非常奇怪的事情。在找到匹配项时,我会 return entry-&gt;value; 并让调用者打印找到的值。
猜你喜欢
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 2017-12-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-24
  • 2012-04-23
  • 2012-05-03
相关资源
最近更新 更多