C++使用链接、删除方法的哈希表

发布于 2024-12-21 08:10:39 字数 3561 浏览 1 评论 0原文

我正在使用链接在 C++ 中实现哈希表。代码构建没有错误,并且使用插入方法表构建良好。但是,当我调用删除方法时,我收到以下错误:

HashTable.exe 中 0x00c53be9 处出现未处理的异常:0xC0000005:读取位置 0x00000000 时发生访问冲突。

哈希条目代码:

#include <string>
#include <vector>

template <class T>
class HashEntry
{
private:
    int key; //lookup key
    T value; //hash data
    HashEntry<T> *next;

public:
    HashEntry(int key, T value);
    HashEntry();
    int& getKey();
    T& getValue();
    void setValue(T value);
    HashEntry<T>* getNext();
    void setNext(HashEntry *next);
    bool operator == (HashEntry& rhs);
    bool operator != (HashEntry& rhs);
    HashEntry<T>& operator = (HashEntry& rhs);
};

template <class T> 
HashEntry<T>::HashEntry(int key, T value)
{
    this->key = key;
    this->value = value;
    this->next= nullptr;
}

template <class T>
HashEntry<T>::HashEntry()
{
    this->key = 0;
    this->next= nullptr;
}

template <class T>
int& HashEntry<T>::getKey()
{
    return key;
}

template <class T>
T& HashEntry<T>::getValue()
{
    return value;
}

template <class T>
void HashEntry<T>::setValue(T value)
{
    this->value = value;
}

template <class T>
HashEntry<T>* HashEntry<T>::getNext()
{
    return next;
}

template <class T>
void HashEntry<T>::setNext (HashEntry *next)
{
    this->next = next;
}

template <class T>
bool HashEntry<T>::operator == (HashEntry& rhs)
{
    return ((this->getKey() == rhs.getKey()) && (this->getValue() == rhs.getValue()));
}

template <class T>
bool HashEntry<T>::operator != (HashEntry& rhs)
{
    return ((this->getKey() != rhs.getKey()) && (this->getValue() != rhs.getValue()));
}

template <class T>
HashEntry<T>& HashEntry<T>::operator = (HashEntry& rhs)
{
    this->key = rhs.getKey();
    this->value = rhs.getValue();
    this->next = rhs.getNext();

    return *this;
}

哈希表代码:

template <class T>
class HashTable
{
private:
    std::vector<HashEntry<T>> table;
    static const int DEFAULT_TABLE_SIZE = 128;
    int TABLE_SIZE;


public:

    HashTable();
    void insert(int key, T value);
    void remove(int key);
    void get(int key);
    ~HashTable();
};

template <class T>
HashTable<T>::HashTable()
{
    TABLE_SIZE = DEFAULT_TABLE_SIZE;
    table.resize(TABLE_SIZE);
}

删除方法代码:

template <class T>
void HashTable<T>::remove(int key)
{
    int hashFunc = (key % TABLE_SIZE);

    if (table[hashFunc] != HashEntry<T>())
    {
        HashEntry<T> prevEntry = HashEntry<T>();
        HashEntry<T> entry = table[hashFunc];
        while (entry.getNext() != nullptr && entry.getKey() != key)
        {
            prevEntry = entry;
            entry = *entry.getNext();
        }
        if (entry.getKey() == key)
        {
            if (prevEntry == HashEntry<T>())
            {
                HashEntry<T> nextEntry = *entry.getNext(); //Where the exception is thrown
                entry = HashEntry<T>();
                table[hashFunc] = nextEntry;
            }

            else
            {
                HashEntry<T> *next = entry.getNext();
                entry = HashEntry<T>();
                prevEntry.setNext(next);
            }
        }
    }
}

I'm implementing a Hash Table in C++ using chaining. The code builds with no errors and the table constucts fine using the insert method. However, when I call the remove method I receive the following error:

Unhandled exception at 0x00c53be9 in HashTable.exe: 0xC0000005: Access violation reading location 0x00000000.

Hash Entry Code:

#include <string>
#include <vector>

template <class T>
class HashEntry
{
private:
    int key; //lookup key
    T value; //hash data
    HashEntry<T> *next;

public:
    HashEntry(int key, T value);
    HashEntry();
    int& getKey();
    T& getValue();
    void setValue(T value);
    HashEntry<T>* getNext();
    void setNext(HashEntry *next);
    bool operator == (HashEntry& rhs);
    bool operator != (HashEntry& rhs);
    HashEntry<T>& operator = (HashEntry& rhs);
};

template <class T> 
HashEntry<T>::HashEntry(int key, T value)
{
    this->key = key;
    this->value = value;
    this->next= nullptr;
}

template <class T>
HashEntry<T>::HashEntry()
{
    this->key = 0;
    this->next= nullptr;
}

template <class T>
int& HashEntry<T>::getKey()
{
    return key;
}

template <class T>
T& HashEntry<T>::getValue()
{
    return value;
}

template <class T>
void HashEntry<T>::setValue(T value)
{
    this->value = value;
}

template <class T>
HashEntry<T>* HashEntry<T>::getNext()
{
    return next;
}

template <class T>
void HashEntry<T>::setNext (HashEntry *next)
{
    this->next = next;
}

template <class T>
bool HashEntry<T>::operator == (HashEntry& rhs)
{
    return ((this->getKey() == rhs.getKey()) && (this->getValue() == rhs.getValue()));
}

template <class T>
bool HashEntry<T>::operator != (HashEntry& rhs)
{
    return ((this->getKey() != rhs.getKey()) && (this->getValue() != rhs.getValue()));
}

template <class T>
HashEntry<T>& HashEntry<T>::operator = (HashEntry& rhs)
{
    this->key = rhs.getKey();
    this->value = rhs.getValue();
    this->next = rhs.getNext();

    return *this;
}

Hash Table code:

template <class T>
class HashTable
{
private:
    std::vector<HashEntry<T>> table;
    static const int DEFAULT_TABLE_SIZE = 128;
    int TABLE_SIZE;


public:

    HashTable();
    void insert(int key, T value);
    void remove(int key);
    void get(int key);
    ~HashTable();
};

template <class T>
HashTable<T>::HashTable()
{
    TABLE_SIZE = DEFAULT_TABLE_SIZE;
    table.resize(TABLE_SIZE);
}

Remove Method Code:

template <class T>
void HashTable<T>::remove(int key)
{
    int hashFunc = (key % TABLE_SIZE);

    if (table[hashFunc] != HashEntry<T>())
    {
        HashEntry<T> prevEntry = HashEntry<T>();
        HashEntry<T> entry = table[hashFunc];
        while (entry.getNext() != nullptr && entry.getKey() != key)
        {
            prevEntry = entry;
            entry = *entry.getNext();
        }
        if (entry.getKey() == key)
        {
            if (prevEntry == HashEntry<T>())
            {
                HashEntry<T> nextEntry = *entry.getNext(); //Where the exception is thrown
                entry = HashEntry<T>();
                table[hashFunc] = nextEntry;
            }

            else
            {
                HashEntry<T> *next = entry.getNext();
                entry = HashEntry<T>();
                prevEntry.setNext(next);
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

许仙没带伞 2024-12-28 08:10:39
while (entry.getNext() != nullptr && entry.getKey() != key)
{
    prevEntry = entry;
    entry = *entry.getNext();
}

几行后,使用上面生成的条目:

HashEntry<T> nextEntry = *entry.getNext(); //Where the exception is thrown

while“使”entry.getNext()成为nullptr。并且,稍后,您尝试取消引用它。取消引用 nullptr... 是一件坏事 (tm)。

顺便说一句,你为什么不对指针进行操作?我可能是错的,但是看看你的代码,我有一种感觉,你想修改原始对象......而本地对象看起来像副本。

while (entry.getNext() != nullptr && entry.getKey() != key)
{
    prevEntry = entry;
    entry = *entry.getNext();
}

Few lines later, using entry generated above:

HashEntry<T> nextEntry = *entry.getNext(); //Where the exception is thrown

The while "makes" entry.getNext() a nullptr. And, later, you are trying to dereference it. And dereferencing nullptr... is a Bad Thing (tm).

Btw., why aren't you operating on pointers? I may be wrong, but looking at your code, I have a feeling that you want to modify original objects... and local objects looks like copies.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文