我试图完成一个我们实现哈希表的赋值。我已经使用链接的节点列表来执行此操作。我的Hash
类是纯虚拟类,因为它的hash
函数是纯虚函数。 Hash
类也是模板类。
我已经成功地实现了该类的int和float版本。但是当我尝试实现一个字符串版本并实例化一个对象时,它给了我这个错误:
在抛出' std :: logic_error'的实例后终止调用 what():basic_string :: _ S_construct null无效
根据我的阅读,这与使用std::string
实例化NULL
对象有关。我只是没有看到我这样做的地方。
我提前为我的代码有点混乱而道歉,并感谢愿意提供帮助的任何人!
/******************************************************************
* Class:
* Hash
* Summary:
* This is a class for a abstract "hash" data type.
*****************************************************************/
#ifndef HASH_H
#define HASH_H
#include <iomanip>
#include <iostream>
#include <string>
#include "node.h"
template <class T>
class Hash
{
//private:
public:
node <T> * table; // hash table
int numList; // number of items in hash table
int numItems; // number of lists in the hash table
public:
// non-default constructor
Hash(int numBuckets) throw (const char *)
{
try
{
table = new node<T>[numBuckets];
for (int i = 0; i < numBuckets; i++)
{
table[i].setValue(T());
}
this->numList = numBuckets;
this->numItems = 0;
}
catch (std::bad_alloc)
{
this->numList = 0;
this->numItems = 0;
for (int i = 0; i < numBuckets; i++)
this->table[i] = node<T>();
throw "ERROR: Unable to allocate memory for the hash.";
}
}
// destructor
~Hash() { clear(); };
// pure virtual function hash function
virtual int hash(const T & t)const = 0;
// return capacity
int capacity() const { return numList; }
// is table empty?
bool empty() const { return numItems == 0; }
//display
void display()
{
for(int i = 0; i < numList; i++)
{
std::cout << std::setw(10) << i
<< " : " << table[i].size() << std::endl;
}
}
// return numItems
int size() const { return numItems; }
// copy constructor
Hash(const Hash <T>& rhs) throw (const char *) : table(NULL), numItems(0), numList(0)
{
*this = rhs;
}
// clear the dynamically allocated memory
void clear();
// assignment operator
Hash <T> & operator = (const Hash <T> & rhs) throw (const char *);
//find - return true if found, false if else.
bool find(const T & t) const;
// insert
void insert(const T & t);
};
//insert
template <class T>
void Hash <T> :: insert(const T & t)
{
int hashKey = hash(t);
node <T> * newEntry = new node<T>(hashKey, t);
//check initial hashKey slot
if (table[hashKey].getValue() == T())
{
table[hashKey] = newEntry;
numItems++;
return;
}
else
{
// hashKey++;
for (int i = 0; i < numList; i++)
{ // check the remaining nodes
if (table[hashKey].getValue() == T())
{
table[hashKey] = newEntry;
numItems++;
return;
}
hashKey = (hashKey + 1) % capacity();
}
hashKey = hash(t); // reset hashKey
if (table[hashKey].pNext != NULL)
{
node <T> * ptr = &table[hashKey];
for (ptr; ptr->pNext != NULL; ptr = ptr->pNext) {};
if (ptr->pNext == NULL)
{
ptr->pNext = newEntry;
numItems++;
return;
}
}
else if (table[hashKey].pNext == NULL)
{
table[hashKey].pNext = newEntry;
numItems++;
}
}
}
// find - return true if found, false if else.
template <class T>
bool Hash <T> :: find(const T & t) const
{
int hashKey = hash(t);
for (int i = 0; i < numList; i++)
{
if (table[hashKey].getValue() == t)
return true;
node <T> * ptr = &table[hashKey];
if (ptr->getValue() == t)
return true;
while (ptr != NULL)
{
if (ptr->getValue() == t)
return true;
ptr = ptr->pNext;
}
hashKey = (hashKey + 1) % capacity();
}
return false;
}
// clear the hash table
template <class T>
void Hash <T> :: clear()
{
delete [] table;
}
// assignment operator
template <class T>
Hash <T> & Hash<T> :: operator =(const Hash <T> & rhs) throw (const char *)
{
// allocate if necessary
if (rhs.numList != numList)
{
try
{
node <T> * tableNew = new node <T> [rhs.numList];
delete [] table;
numList = rhs.numList;
table = tableNew;
}
catch (std::bad_alloc)
{
throw "ERROR: Unable to allocate memory for the hash";
}
}
// copy the data
for (int i = 0; i < numList; i++)
table[i] = rhs.table[i];
numItems = rhs.numItems;
// return this
return *this;
}
#endif // HASH_H
和node.h
#ifndef NODE_H
#define NODE_H
#include <cassert>
#include <iostream>
template <class T>
class node
{
private:
int key;
T value;
public:
node * pNext;
// default constructor
node() : key(0), value(0), pNext(NULL) {};
// non-default constructor
node(int pKey, T pVal) : key(pKey), value(pVal), pNext(NULL) {};
// set value
void setValue(T value)
{
this->value = value;
}
// key - getter
int getKey()
{
return key;
}
// value - getter
T getValue()
{
return value;
}
node * getNext()
{
return pNext;
}
void setNext(node * newNext)
{
this->pNext = newNext;
}
void setNext(node & newNext)
{
pNext = newNext;
}
bool checkNode()
{
if (this->pNext == NULL)
return true;
else
return false;
}
void setNULL()
{
this = NULL;
}
node<T> operator=(node<T> * rhs)
{
this->key = rhs->key;
this->value = rhs->value;
this->pNext = rhs->pNext;
}
};
#endif //NODE_H
和spellCheck.cpp - 实现Hash类。
/***********************************************************************
* Module:
* Week 12, Spell Check
*
* Author:
*
* Summary:
* This program will implement the spellCheck() function
************************************************************************/
#include <iostream>
#include <fstream>
#include <string>
#include "spellCheck.h"
#include "hash.h"
#include <fstream>
using namespace std;
/******************************************************
* Class: SHash
* Author:
* Summary: A derived hash table for strings
*****************************************************/
class SHash : public Hash <string>
{
public:
SHash(const int numBuckets) throw (const char *) : Hash <string> (numBuckets) {}
SHash(const SHash & rhs) throw (const char *) : Hash <string> (rhs) {}
//hash function for strings
int hash(const string & s) const
{
int hashValue = 0;
for (int i = 0; i < s.length(); ++i)
{
char c = s[i];
hashValue = (hashValue + c);
}
return hashValue;
}
};
/*****************************************
* SPELL CHECK
* Prompt the user for a file to spell-check
****************************************/
void spellCheck()
{
SHash dictionary(101);
};