【问题标题】:Implementing a Hash Table (rehash scope error)实现哈希表(重新哈希范围错误)
【发布时间】:2012-04-15 17:31:37
【问题描述】:

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

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;
                    }

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

编辑:澄清一下,初始哈希表的容量为 0(这是项目要求之一)。因此,当我尝试向表中添加项目时,会执行此 if 语句(因为大小为 0 且上限为 0,我们必须保持负载因子为 1)。我可以确认,一旦表格到达第一次和第二次“万岁”检查,htable-&gt;cap(这是阵列的总容量)为 1,这应该是。唯一弄乱的是存储桶 0(在这种情况下是唯一的存储桶)。无论出于何种原因,它在退出 if 语句之前为空,但之后不为空。

我正在发布我的整个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++ scope hashtable


    【解决方案1】:

    嗯,这是 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 对象,然后删除旧哈希表。

    【讨论】:

    • 感谢您的 cmets,但我确实需要纠正一些问题。首先, tempht 不是指针。这是一个实际的硬拷贝,这样我可以释放 htable 的内存,但仍然使用它包含的值。我确实尝试重命名 HOORAY 语句并确认它只是第一个 HOORAY 出现。另一件事是,当我重新散列时,旧表中没有任何内容,因此新表中也应该没有任何内容,并且它直到退出 if 语句,然后无论出于何种原因,项目不再为 NULL。再次感谢您的 cmets,并继续努力修复它。
    • 好的,哈希表类已经发布,忽略系统暂停,我只是想弄清楚问题最初出在哪里。
    • 是的,这正是问题所在。当我逐步完成时,我注意到析构函数在 if 语句的末尾被调用,并且最初我无法弄清楚为什么,直到我意识到它试图破坏我的 tempht 对象。只要您提到它们共享相同的内存块,就完全可以理解发生了什么。您的解决方案完美!非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 2012-06-03
    • 1970-01-01
    • 2011-10-14
    • 2011-09-15
    • 2021-02-13
    • 1970-01-01
    相关资源
    最近更新 更多