【问题标题】:Hash table's resizing crashes program哈希表调整大小崩溃程序
【发布时间】:2021-03-14 11:07:12
【问题描述】:

我正在尝试使用 STL 对列表在 C++ 中实现哈希表。初始 maxSize 我设置为 1,并且我想在其 currentSize 大于最大容量的 75% 时将哈希表的大小增加两倍。我收到错误“无法取消引用结束列表运算符”。这是我的实现:

template<class V>
class HashTable {
public:
    int currentSize;
    int maxSize;
    std::list<std::pair<std::string, V> > *arr;

    HashTable() {
        this->currentSize = 0; 
        this->maxSize = 1; 
        this->arr = new std::list<std::pair<std::string, V> >[maxSize];
        arr->assign(maxSize, std::pair<std::string, V>());
    }
    ~HashTable() {
        delete[] arr;
    }

    void add(std::string key, V value) {
        if (currentSize >= 0.75 * maxSize) {
            rehash();
        }
        currentSize++;
        int idx = hashFunction(key);
        std::list<std::pair<std::string, int> >::iterator it = arr->begin();
        std::advance(it, idx);
        it = arr->erase(it);
        arr->insert(it, std::pair<std::string, V> (key, value));
    }

    int hashFunction(std::string key) {
        int total = 0;
        for (int i = 0; i < key.length(); i++) {
            total += int(key[i]) * pow(31, key.length() - i - 1);
        }
        return total % maxSize;
    }

    void rehash() {
        maxSize *= 2;
        std::list<std::pair<std::string, V> > *newArr = new std::list<std::pair<std::string, V> >[maxSize];
        newArr->assign(maxSize, std::pair<std::string, V>());
        for (auto it = arr->begin(); it != arr->end(); it++) {
                int idx = hashFunction(it->first);
                it = arr->begin();
                std::advance(it, idx);
                it = arr->erase(it);
                newArr->insert(it, std::pair<std::string, V>(it->first, it->second));
        }
        delete[] arr;
        arr = newArr;
    }

有趣的事实是,当我对 maxSize 进行硬编码时,例如通过将其设置为 20 然后添加 2 个元素,它可以工作并输出例如"1: abc -> 123, 5: bca -> 42"。

【问题讨论】:

  • std::list&lt;std::pair&lt;std::string, V&gt; &gt; *arr; -- 为什么不std::vector&lt;std::list&lt;std::pair&lt;std::string, V&gt; &gt;&gt; arr;?这样您就不必进行任何手动内存管理。
  • 我看到 Rule of Three 违规,但我不确定这是否是错误的原因。为什么使用手动内存管理而不是std::vector?
  • 而且您似乎没有使用该数组。您只使用该数组的第一个元素。
  • int main() { HashTable&lt;int&gt; h1; HashTable&lt;int&gt; h2 = h1; } -- 那个简单的程序出现双重删除错误。

标签: c++ algorithm hashtable


【解决方案1】:

显示的代码中有多个错误。

在你的rehash:

it = arr->erase(it);

erase() 总是返回一个迭代器,指向刚刚被擦除的那个值之后的值。这就是它的工作原理。因此,如果it 已经碰巧引用了arr 中的最后一个值,erase() 将删除它并有效地返回end()。之后:

for (  ... ; it++) 

与往常一样,这最终会增加 it。但在这种情况下,it 已经是 end()。递增 end() 迭代器值是未定义的行为。

另外:

newArr->insert(it, ...

it 不是newArr 的迭代器,它是另一个容器的迭代器。迭代器只能作为参数传递给它自己的容器的insert()。更多未定义的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    • 2013-12-21
    • 1970-01-01
    • 2012-10-14
    • 2014-04-21
    相关资源
    最近更新 更多