【问题标题】:count total hash collisions in template class c++计算模板类 C++ 中的总哈希冲突
【发布时间】:2018-04-14 07:57:14
【问题描述】:

创建了一个模板类,将字符串散列为 0 - 999 3 种不同方式的整数。我正在尝试比较散列值和索引值,当它们不同时添加到计数中,然后返回该数字以获得冲突总数。我的问题是我是否正确地执行了此操作,因为我只是在猜测我何时将所有这些放在一起。

代码:

#include <string>

#include <list>

template<typename T>
class Hash
{
protected:

    // Capacity of the hash table
    static const size_t SIZE = 1000;

    // Defines an entry in the hash table
    class Entry
    {
    public:
        std::string key;
        T value;
        bool used;
        Entry()
        {
            used = false;
            value = T();
        }
    };

    // The hash table entries
    Entry entries[SIZE];

    // Hash function #1
    size_t hash1(const std::string& k) const;

    // Hash function #2
    size_t hash2(const std::string& k) const;

    // Hash function #3
    size_t hash3(const std::string& k) const;

    // Calculate the hash of a given key
    //  TODO: change this to use the desired hash function
    size_t hash(const std::string& k) const
    {
        return hash1(k);
    }

    // Perform linear probing on the given key and index to get index
    size_t probe(const std::string& k, size_t i) const;
public:
    // Access data item in hash for the given key
    T& operator[](const std::string& k);

    void print() const
    {
        for (size_t i = 0; i < SIZE; i++)
            std::cout << i << "-" << entries[i].used << "-" << entries[i].key
                    << "-" << entries[i].value << std::endl;
    }
    size_t collision(const std::string& k) const;
};

template<typename T>
size_t Hash<T>::hash1(const std::string& k) const
{
    int index = 0;
    for (size_t i = 0; i < k.size(); i++)
        index += k[i];
    return index % SIZE;
}

template<typename T>
size_t Hash<T>::hash2(const std::string& k) const
{
    int index = 0;
    for (size_t i = 0; i < k.size(); i++)
    {
        index += (k[i] + 27 * k[i] + 729 * k[i]);
    }
    return index % SIZE;
}

template<typename T>
size_t Hash<T>::hash3(const std::string& k) const
{
    int index = 0;
    for (size_t i = 0; i < k.size(); i++)
    {
        index += 37 * index + k[i];
    }
    return index % SIZE;
}

template<typename T>
size_t Hash<T>::probe(const std::string& k, size_t i) const
{
    int index = i;
    int count = 0;
    while (entries[index].used && entries[index].key != k && count < SIZE)
        index = (index + 1) % SIZE;
    return index;
}

template<typename T>
T& Hash<T>::operator[](const std::string& k)
{
    int index = hash(k);
    if (entries[index].used && entries[index].key != k)
        index = probe(k, index);
    if (!entries[index].used)
    {
        entries[index].key = k;
        entries[index].used = true;
    }
    return entries[index].value;
}

template<typename T>
size_t Hash<T>::collision(const std::string& k) const
{
    int count = 0;
    for (int j = 0; j < SIZE; j++)
    {
        if (j == entries[j].value)
        {
            count++;
        }
    }
    return count;
}

由于列表的大小是常数 1000,因此索引值始终为 0 到 999。知道这一点,如果我将该数字与散列值 (entries[j].value) 进行比较并且它们是相同的,那么我知道值是相同的并且发生了冲突,所以我可以添加到计数中。

我正在尝试这种方式,因为我的教授说“你可以 通过检查哈希表中的每个条目并将存储的键值的哈希值与表中的索引进行比较来确定这一点。”老实说,我不确定他的意思。我要提前道歉,因为我有强烈的感觉这是完全错误的。

【问题讨论】:

  • 我想他是想比较index == hash(entries[index].key)
  • 你描述的对我来说听起来不错。键的散列告诉你你的值应该在表中的哪个位置。如果该值不在键的哈希建议的位置的表中,则您发生了冲突。我看到您的代码犯了两个错误:1.它没有考虑到表中的某个位置可能未使用。 2.它不计算密钥的哈希
  • 其实第三个错误?为什么要传入k
  • 我投票结束这个问题,因为它属于codereview.stackexchange.com

标签: c++ templates hash


【解决方案1】:

键的哈希值告诉您值应该在表中的哪个位置。如果值不在键的哈希建议的位置的表中,则您发生了冲突。

您的代码在计算我看到的冲突时犯了两个错误:1. 它没有考虑到表中的某个位置可能未使用。 2. 它不计算和测试密钥的哈希值。

template<typename T>
size_t Hash<T>::collision() const // doesn't seem to be any reason to pass in a key
{
    size_t count = 0; // returning size_t, might as well use size_t
                      // negative collisions isn't a possibility anyway
    for (size_t j = 0; j < SIZE; j++) // compare like datatypes where possible
    {
        if (entries[j].used) // can't be a collision if the location is empty
        {
            size_t index = hash(entries[j].key); // get correct index for key
            if (j != index) // increment count if in wrong slot in table
            {
                count++;
            }
        }

    }
    return count;
}

【讨论】:

  • 啊,谢谢!我知道为什么我没有想到这一点,这比我试图做的更有意义。你是救生员。 :)
猜你喜欢
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-13
相关资源
最近更新 更多