实现哈希表(rehash范围错误)

Implementing a Hash Table (rehash scope error)

本文关键字:错误 范围 rehash 哈希表 实现      更新时间:2023-10-16

我的代码中出现了一个非常奇怪的错误。这项作业是为我正在上的一门课准备的,本质上我们正在学习如何实现哈希表。我遇到的错误是,当我尝试重新安装到更大的尺寸时。以下是代码中给出问题的部分,我将更全面地解释问题是什么

if(htable->size>=htable->cap)
                    {
                        cout<<htable->cap<<endl;
                        HashTable tempht=*htable;
                        delete htable;
                        htable=new HashTable((tempht.cap * 2) + 1);

                        for (size_t i=0; i<tempht.cap; i++)
                        {
                            Node* n=tempht.table[i];
                            while (n!=NULL)
                            {
                                htable->add(n->item);
                                n=n->next;
                            }
                        }
                        if (htable->table[0]==NULL)
                        {
                            cout<<"HOORAY!"<<endl;
                        }
                    }
                    if (htable->table[0]==NULL)
                    {
                        cout<<"HOORAY!"<<endl;
                    }
                    else
                    {
                        cout<<htable->table[0]->item<<endl;
                    }

htableHashTable变量。在HashTable类中,它包含一个数组Node*(节点只是我创建的对象,其中包含一个字符串和指向链中下一项的指针)。这部分代码只是试图重新散列到一个更大的表。我遇到的问题是,一旦我退出第一个if语句,我的表的第一个值就不再等于NULL(我正在运行的测试将一个没有任何内容的表重新灰成一个仍然没有任何内容但容量更大的表)。当我运行代码时,第一个htable->table[0]==NULL通过,而第二个没有通过,尽管除了退出if语句之外没有任何更改(我的预期结果是table[0]应该为NULL)。我最好的猜测是这是某种范围错误,但老实说,我看不出问题出在哪里。任何帮助都将不胜感激。

编辑:为了澄清,初始哈希表的容量为0(这是项目要求之一)。因此,当我试图向表中添加一个项时,会执行if语句(由于大小为0,上限为0,因此我们必须保持负载因子为1)。我可以确认,一旦表达到第一次和第二次"Hooray"检查,htable->cap(数组的总容量)就是1,这就是它应该是的。唯一被搞砸的是bucket 0(在这种情况下,它是唯一的bucket)。无论出于何种原因,它在退出if语句之前为null,但在退出之后则不为null。

我正在发布我的整个HashTable课程,如果你发现什么,请告诉我。

#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include "Node.h"
using namespace std;
class HashTable
{
public:
    Node** table;
    int size;
    int cap;
    HashTable (int c)
    {
        size=0;
        cap=c;
        table = new Node*[cap];
        if (cap>0)
        {
            for (size_t i=0; i<cap; ++i)
            {
                table[i]=NULL;

            }
        }
    }
    ~HashTable()
    {
        delete table;
    }
    size_t hash(string thing)
    {
        size_t total=0;
        int asci;
        char c;
        size_t index;
        for (size_t i=0; i<thing.length(); i++)
        {
            total=total*31;
            c=thing[i];
            asci=int(c);
            total=asci+total;
        }
        index=total%cap;
                    cout<<"index"<<index<<endl;
            system("pause");
        return index;
    }
    void add(string thing)
    {

            size_t index;
            index=hash(thing);
                        cout<<"index "<<index<<endl;
            system("pause");
            Node* temp=table[index];
            if (temp==NULL)
            {
            cout<<"Here"<<endl;
            system("pause");
            }
            else
            {
                            cout<<"Here2"<<endl;
            system("pause");
                        cout<<"temp"<<temp->item<<endl;
            system("pause");
            }
            Node* n = new Node(thing);
            cout<<"n"<<n->item<<endl;
            system("pause");
            if (temp==NULL)
            {
                table[index]=n;
            }
            else
            {
                while (temp->next!=NULL)
                {
                    temp=temp->next;
                }
                temp->next=n;
            }
        size++;
    }
    Node* find(string search)
    {
        Node* n= NULL;
        size_t index;
        if(cap!=0)
        {
        index=hash(search);
        Node* temp=table[index];
        while (temp!=NULL)
        {
            if (temp->item==search)
            {
                n=temp;
                return n;
            }
        }
        }
        return n;
    }
    void remove (string thing)
    {
        if (find(thing)==NULL)
        {
            return;
        }
        else
        {
            size_t index;
            index=hash(thing);
            Node* temp=table[index];
            if (temp->item==thing)
            {
                table[index]=temp->next;
                delete temp;
            }
            while (temp->next!=NULL)
            {
              if (temp->next->item==thing)
              {
                  Node* temp2=temp->next;
                  temp->next=temp->next->next;
                  delete temp2;
                  break;
              }
            }
        }
        size--;
    }
    void print(ofstream &ofile)
    {
        for (size_t i=0; i<cap; i++)
        {
            Node* n=table[i];
            ofile<<"hash "<<i<<":";
            while (n!=NULL)
            {
                ofile<<" "<<n->item;
                n=n->next;
            }
        }
    }
};

好吧,这是C++,我更喜欢Java,但我会尝试一下。

问题出在上

                HashTable tempht=*htable;
                delete htable;

毕竟是块。

看,第一行写着"将所有成员从*htable复制到tempht"。现在tempht和htable共享它们的表内存,因为表只是一个指向构造时分配的内存的指针,而您只是复制了指针。您希望它复制表中的节点,但它并没有这样做。

所以现在在表中有两个指针值相同的不同HashTable对象。现在,当释放tempht时,析构函数对表指针调用free,从而有效地释放对象htable和tempht中的表数据。

你真正想做的是写一个复制构造函数,或者做一些类似的事情:

HashTable *tempht=htable;
htable=new HashTable((tempht->cap * 2) + 1);
for (size_t i=0; i<tempht->cap; i++)
{
    Node* n=tempht->table[i];
    while (n!=NULL)
    {
        htable->add(n->item);
        n=n->next;
    }
}
if (htable->table[0]==NULL)
{
    cout<<"HOORAY!"<<endl;
}
delete tempht;

看看我真正做的是如何将tempht更改为指针,使用它指向旧哈希表,同时将其中的所有节点复制到新的htable对象,然后删除旧哈希表。