Реализация хэш-таблицы (ошибка перефразирования области) - PullRequest
0 голосов
/ 02 апреля 2012

Я получаю очень странную ошибку в своем коде. Это назначение для класса, который я беру, и, по сути, мы учимся, как реализовать хеш-таблицу. Ошибка, которую я получаю, когда я пытаюсь перефразировать в больший размер. Вот часть кода, которая дает мне проблему, и я более подробно объясню, в чем проблема.

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). Я могу подтвердить, что как только таблица достигает первой и второй проверок «Ура», htable->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;
            }
        }
    }

};

1 Ответ

0 голосов
/ 02 апреля 2012

Ну, это 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, затем удаляя старый Hashtable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...