实现哈希表(重新哈希范围错误)

时间:2012-04-02 01:30:34

标签: c++ scope hashtable

我的代码中出现了一个非常奇怪的错误。这个赋值适用于我正在学习的类,基本上我们正在学习如何实现哈希表。我得到的错误是当我尝试重新调整到更大的尺寸时。这是代码中给我问题的部分,我将更全面地解释问题所在。

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->table[0]==NULL通过而第二个没有通过,尽管除了退出if语句之外没有任何更改(我的预期结果是table[0]应该为NULL)。我最好的猜测是它有某种范围错误,但老实说我看不出问题出在哪里。任何帮助将不胜感激。

编辑:为了澄清,初始哈希表的容量为0(这是项目要求之一)。因此,当我尝试向表中添加项时,执行此if语句(因为大小为0且上限为0,所以我们必须保持1的加载因子)。我可以确认,一旦表到达第一个和第二个“Hooray”检查,htable->cap(这是数组的总容量)是1,这应该是它。唯一被弄乱的是桶0(在这种情况下是唯一的桶)。无论出于何种原因,在退出if语句之前它都是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;
            }
        }
    }

};

1 个答案:

答案 0 :(得分:0)

嗯,这是C ++,而且我更像是一个Java家伙,但我会抨击它。

使用

解决问题IS
                HashTable tempht=*htable;
                delete htable;
毕竟

阻止。

看,第一行说“将所有成员从* htable复制到tempht”。所以现在tempht和htable分享他们的表内存,因为table只是指向构造时分配的内存的指针,你刚刚复制了指针。您希望它复制表中的节点,但它没有这样做。

所以现在你有两个不同的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;

看看我所做的一切是如何改变指针,在将所有节点从它复制到新的htable对象时使用它来指向旧的哈希表,然后删除旧哈希表。