在 C++ 中实现将字符串映射到数组的散列 table。我一直收到 "Debug Assertion Failed",我不知道为什么

Implementing a hash table that maps strings to an array in C++. I keep getting "Debug Assertion Failed" and I don't know why

正如标题所说,我正在尝试实现一个散列 table,它使用散列函数将字符串映射到数组中。散列table使用单独的链接方法来处理冲突,因此需要链表(散列table实现为链表数组)。我一直收到 "Debug Assertion Failed" 错误,但我似乎找不到问题所在。我用我的代码尝试了很多东西,尤其是在构造函数和析构函数上,但仍然没有结果。这是我所有的代码。请帮助我仍然是编程的新手。我正在使用 Microsoft Visual Studio 2010 Ultimate。

文件:main.cpp

#include <iostream>
#include "HashTable.h"
using namespace std;

void simpleTest();

int main()
{
    simpleTest();
    system("pause");
    return 0;
}

void simpleTest()
{
    HashTable ht1(9);
    ht1.insert("bat");
    ht1.insert("lion");
    ht1.insert("panther");
    ht1.insert("cat");
    ht1.insert("michael");
    ht1.insert("rhinoceros");
    ht1.insert("duck");
    ht1.insert("bear");
    ht1.insert("shark");
    ht1.insert("elephant");
    ht1.insert("hippopotamus");
    ht1.insert("john");
}

文件:HashTable.h

#pragma once

#include "LinkedList.h"

class HashTable
{
public:
    HashTable(); //default constructor
    HashTable(int); //one parameter constructor
    HashTable(const HashTable&); //copy constructor
    ~HashTable(); //destructor
    HashTable& operator=(const HashTable&); //assignment operator
    bool insert(const string&);
    bool remove(const string&);
    bool search(const string&) const;
    int size() const; //return numOfItems
    int maxSize() const; //return arrSize
    int loadFactor() const;
    vector<string> intersection(const HashTable&) const;
    vector<string> unions(const HashTable&) const;
    vector<string> difference(const HashTable&) const;
private:
    LinkedList* arr;
    int arrSize;
    int numOfItems;
    int hashFunc(const string&) const;
    int getPrime(int) const;
    bool isPrime(int) const;
    void deepCopy(const HashTable& h);
    vector<string> get() const; //returns a vector of all the strings in the HashTable
};

文件:HashTable.cpp

#include "HashTable.h"

#include <iostream>
using namespace std;

//PRIVATE MEMBER FUNCTIONS

int HashTable::hashFunc(const string& s) const //hash function
{
    int hashVal=0,asc;
    for(int i=0;i<s.size();i++)
    {
        asc=s[i]>96?s[i]-96:s[i]-64;
        hashVal=(hashVal*32+asc)%arrSize;
    }
    cout<<hashVal<<endl;
    return hashVal;
}

int HashTable::getPrime(int n) const
{
    int i=2*n;
    while(!isPrime(i))
        i++;
    return i;
}

bool HashTable::isPrime(int n) const
{
    bool isPrime=true;
        for(int count=2;count<n && isPrime; count++)
            if(n%count==0)
                isPrime=false;
    return isPrime;
}

void HashTable::deepCopy(const HashTable& h)
{
    if(arr!=NULL)
        delete arr;
    numOfItems=h.size();
    arrSize=h.maxSize();
    arr=new LinkedList[arrSize];
    for(int i=0;i<arrSize;i++)
        arr[i]=h.arr[i];
}

vector<string> HashTable::get() const //returns a vector of all the strings in the hash table
{
    vector<string> v,tmp_v;
    for(int i=0;i<maxSize();i++)
    {
        tmp_v=arr[i].get();
        for(int j=0;j<tmp_v.size();j++)
            v.push_back(tmp_v[j]);
    }
    return v;
}

/*END OF PRIVATE MEMBER FUNCTIONS*/

/*==========================================================================*/

//PUBLIC MEMBER FUNCTIONS

HashTable::HashTable() //default constructor
{
    arrSize=101;
    arr=new LinkedList[arrSize];
    numOfItems=0;
}

HashTable::HashTable(int n) //creates a hash table to store n items where the size of the array is the smallest prime number >= 2*n
{
    arrSize=getPrime(n);
    arr=new LinkedList[arrSize];
    numOfItems=0;
}

HashTable::HashTable(const HashTable& h) //copy constructor
{
    deepCopy(h);
}

HashTable::~HashTable() //destructor
{
    for(int i=0;i<arrSize;i++)
        arr[i].deleteList();
    delete arr;
}

HashTable& HashTable::operator=(const HashTable& h) //assignment operator
{
    if(this!=&h)
    {
        if(h.arr!=NULL)
            delete arr;
        deepCopy(h);
    }
    return *this;
}

bool HashTable::insert(const string& s) //inserts string s if it doesn't exist in the hash table and returns 1 if insertion successful, 0 otherwise
{
    int hash=hashFunc(s);
    bool successOrFail=arr[hash].insert(s);
    numOfItems++;
    return successOrFail;
}

bool HashTable::remove(const string& s) //removes string s if s exist in the hash table and returns 1 if removal successful, 0 otherwise
{
    int hash=hashFunc(s);
    bool successOrFail=arr[hash].remove(s);
    numOfItems--;
    return successOrFail;
}

bool HashTable::search(const string& s) const //returns 1 if s exist in the hash table, 0 otherwise
{
    int hash=hashFunc(s);
    bool found=arr[hash].search(s);
    return found;
}

int HashTable::size() const //returns numOfItems
{
    return numOfItems;
}

int HashTable::maxSize() const //returns arrSize
{
    return arrSize;
}

int HashTable::loadFactor() const //returns the load factor of the hash table
{
    return numOfItems/arrSize;
}

vector<string> HashTable::intersection(const HashTable& h) const //returns a vector of string containing intersection of calling object's data and h's data
{
    vector<string> ret_v;
    vector<string> v=this->get();
    for(int i=0;i<v.size();i++)
        if(h.search(v[i]))
            ret_v.push_back(v[i]);
    return ret_v;
}

vector<string> HashTable::unions(const HashTable& h) const //returns a vector of string containing union of calling object's data and h's data
{
    vector<string> ret_v;
    vector<string> v1=this->get();
    vector<string> v2=h.get();
    for(int i=0;i<v2.size();i++) //push_back all h elements
        ret_v.push_back(v2[i]);
    for(int i=0;i<v1.size();i++) //push_back caller elements that are not found in h
        if(!h.search(v1[i]))
            ret_v.push_back(v1[i]);
    return ret_v;
}

vector<string> HashTable::difference(const HashTable& h) const //returns a vector of string containing set difference of calling object's data and h's data
{
    vector<string> ret_v;
    vector<string> v1=this->get();
    vector<string> v2=h.get();
    for(int i=0;i<v1.size();i++) //push_back caller elements that are not found in h
        if(!h.search(v1[i]))
            ret_v.push_back(v1[i]);
    for(int i=0;i<v2.size();i++) //push_back h elements that are not found in caller
        if(!this->search(v1[i]))
            ret_v.push_back(v2[i]);
    return ret_v;
}

文件:LinkedList.h

#pragma once

#include <cstdlib>
#include <vector>
#include <string>

using namespace std;

class LinkedList
{
public:
    class Node
    {
    public:
        string data;
        Node* next;
        Node(string s):data(s),next(NULL) {};
        Node(string s,Node* nd):data(s),next(nd) {};
    };
    Node* front;
    //member functions
    LinkedList(); //default constructor
    LinkedList(const LinkedList& ls);//copy constructor
    ~LinkedList(); //destructor
    LinkedList& operator=(const LinkedList&); //assignment operator
    bool insert(const string&);
    bool remove(const string&);
    bool search(const string&) const;
    vector<string> get() const;
    void deepCopy(const LinkedList& ls);
    void deleteList();
};

文件:LinkedList.cpp

#include "LinkedList.h"

LinkedList::LinkedList() //default constructor
{
    front=NULL;
}

LinkedList::LinkedList(const LinkedList& ls) //copy constructor
{
    deepCopy(ls);
}

LinkedList::~LinkedList() //destructor
{
    deleteList();
}

LinkedList& LinkedList::operator=(const LinkedList& ls) //assignment operator
{
    if(this!=&ls)
    {
        deleteList();
        deepCopy(ls);
    }
    return *this;
}

bool LinkedList::insert(const string& s)
{
    if(search(s))
        return false;
    front=new Node(s,front);
    return true;
}

bool LinkedList::remove(const string& s)
{
    Node* temp=front;
    if(temp==NULL) //list is empty
        return false;
    if(temp->data==s) //s is first string in list
    {
        front=temp->next;
        delete temp;
        return true;
    }
    else
    {
        while(temp->next!=NULL){
            if(temp->next->data==s)
            {
                Node* deletedNode=temp->next;
                temp->next=temp->next->next;
                delete deletedNode;
                return true;
            }
            temp=temp->next;
        }
        return false;
    }
}

bool LinkedList::search(const string& s) const
{
    Node* temp=front;
    while(temp!=NULL) //Traverse list
    {
        if(temp->data==s)
            return true;
        temp = temp->next;
    }
    return false;
}

vector<string> LinkedList::get() const
{
    vector<string> str_vec;
    for(Node* temp=front;temp!=NULL;temp=temp->next)
        str_vec.push_back(temp->data);
    return str_vec;
}

void LinkedList::deepCopy(const LinkedList& ls)
{
    front=NULL;
    if(ls.front!=NULL) //Only copy if ls is non-empty
    {
        Node* original=ls.front;
        Node* copy;
        copy=new Node(original->data, NULL);
        front=copy;
        original=original->next;
        while(original!=NULL) //Traverse the original copying each node
        {
            copy->next=new Node(original->data, NULL);
            copy=copy->next;
            original=original->next;
        }
    }
}

void LinkedList::deleteList()
{
    Node* tmp;
    while(front!=NULL){
        tmp=front->next;
        delete front;
        front=tmp;
    }
}

您的问题在这里:

HashTable::~HashTable() //destructor
{
    for(unsigned int i=0;i<arrSize;i++)
        arr[i].deleteList();

    delete arr;
}

您正在调用 delete arr,但您将 arr 分配给了 new[]。您需要致电:

delete[] arr;