2011-12-15 2 views
2

Я реализую Hash Table в C++, используя цепочку. Код строит без ошибок, и таблица consts прекрасно обрабатывает метод вставки. Однако, когда я вызываю метод remove, я получаю следующую ошибку:C++ Hash Table с использованием цепочки, метод удаления

Необработанное исключение в 0x00c53be9 в HashTable.exe: 0xC0000005: местоположение чтения нарушения доступа 0x00000000.

Hash Вступление Код:

#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 код Таблица:

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); 
      } 
     } 
    } 
} 
+0

Вы получите гораздо лучшие ответы, если вы опубликуете полный компилируемый пример (возможно, на идеоне или таком, чтобы он не загромождал вопрос), включая тестовый код. –

+0

Aw, ничего подобного чтению NULL, чтобы разрушить ваш день. Вы читаете вне границ памяти. –

+0

Я не знаю, является ли это вашей реальной проблемой, но «entry» - это объект, а не указатель, поэтому он не требует звездочки разыменования в '* entry.getNext()'. –

ответ

1
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() a nullptr. И, позже, вы пытаетесь разыменовать его. И разыменование nullptr ... - это Bad Thing (tm).

КВт., Почему вы не работаете с указателями? Возможно, я ошибаюсь, но, глядя на ваш код, у меня возникает ощущение, что вы хотите изменить исходные объекты ... и локальные объекты выглядят как копии.

+0

Либо нуль, либо равное требуемому значению. Если это nullptr, он не работает в if-if 'if (entry.getKey() == key)'. –

+1

Я изменил nullptr просто на NULL, но не могу исправить ошибку. Я попытался удалить звездочку разыменования из * entry.getNext(), но тогда код не компилируется и не выдает ошибку: Ошибка ошибка C2440: 'initializing': не может конвертировать из 'HashEntry *' to 'HashEntry ' –

+0

Во-первых: используйте указатели для управления объектами. Во-вторых: разыменование как 'nullptr', так и' NULL' равно разыменованию '0'. Не делай этого. – Griwes

 Смежные вопросы

  • Нет связанных вопросов^_^