-2
#include <iostream>
#include <cstring>
#include <vector>
#include "list.cpp"
#include <cmath>

using namespace std;

struct HashEntry{
   int key;
   List<string> list;
   HashEntry(int k)
   {        
         key=k;
   } 
}; 

class Hash{
  private:
         HashEntry *Table[100];
         int a;
  public:
         Hash(int A);
         void insert(string word);
         void Lookup(string word);
};    

Hash::Hash(int A)
{
    a=A;
}         

void Hash::insert(string word)
{
   int c=0;
   for (int i=0;i<word.size();i++)
   {                                 
       int b=(int)((a^i)*(word[i]));
       c+=b;
   }
   c%=100;
   List<string> list;
   if (Table[c-1]==NULL)     //if the respective bucket doesnot have any string
   Table[c-1]=new HashEntry(c-1);

   Table[c-1]->list.insertAtTail(word);
}                  


void Hash::Lookup(string word)
{
   int c=0;
   for (int i=0;i<word.size();i++)
   {                                 
     int b=(int)((a^i)*(word[i]));
     c+=b;
   }
   cout<<"one"<<endl;
   c%=100;
   Table[c-1]->list.searchFor(word);
   cout<<"two"<<endl;
}

私は別の連鎖を取ることを使用してハッシュテーブルを作成しています.私のハッシュ関数は、単語内の文字のインデックスとともに力が増加する定数「a」を使用して多項式を作成しています.(a ^ 0xb + a ^ 1xb + a ^ 2xb+...) 、ここで、b はハッシュされている単語の文字であり、最終的な回答の mod(100) を取得します。私が直面している問題はルックアップ関数にあります。ルックアップ関数をテストすると、searchFor () 関数の一部である Linked list クラスは、それ自体は正常に動作しますが、デバッグに使用した cout<<"one" の後にセグメンテーション違反が発生します。お手数をおかけして申し訳ありませんが、ここの問題を理解できません。リンクされたリストのクラス ファイルは以下にあります。問題が発生している関数を貼り付けただけです。

#ifndef __LIST_H
#define __LIST_H
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
/* This class just holds a single data item. */
template <class T>
struct ListItem
{
   vector<string> words;
   T value;
   ListItem<T> *next;
   ListItem<T> *prev;

   ListItem(T theVal)
   {
       this->value = theVal;
       this->next = NULL;
       this->prev = NULL;
   }
};

/* This is the generic List class */
template <class T>
class List
 {
 ListItem<T> *head;

 public:
  // Constructor
  List();

  // Copy Constructor
  List(const List<T>& otherList);

  // Destructor
  ~List();

  // Insertion Functions
  void insertAtHead(T item);
  void insertAtTail(T item);
  void insertAfter(T toInsert, T afterWhat);
  void insertSorted(T item);
  void printList();
  // Lookup Functions
  ListItem<T> *getHead();
  ListItem<T> *getTail();
  void *searchFor(T item);

  // Deletion Functions
  void deleteElement(T item);
  void deleteHead();
  void deleteTail();

  // Utility Functions
  int length();
};

#endif

template <class T>
void List<T>::searchFor(T item)
{    
 ListItem<T> *temp=head;
 if (temp!=NULL)
 {
    while (temp->next!=NULL)
    {
         T sample=temp->value;
         if (sample==item)
         {      
             cout<<"String found";   
             return;
         }
         temp=temp->next;
    }
    T s=temp->value;
    if (s==item)
    {
       cout<<"String found";        
       return;
    }
  }                   
}
4

1 に答える 1

0

あなたが持っているバグの1つを見つけることにつながった上記の私のコメントに加えて、私はこれを追加します:

クラッシュする理由は、Hashクラスがハッシュ テーブルを誤って管理しているためです。まず、100 個のHashEntryポインターの配列を割り当てます。

HashEntry *Table[100];

これらのポインターを何も設定していないことに注意してください。つまり、誰が何を知っているかを指しています。運が良ければ、彼らは NULL を指すかもしれませんが、その可能性はごくわずかです。宝くじに当選する可能性ははるかに高くなります。したがって、ランダムなメモリにアクセスしています-そしてそれは悪いことです.

その解決策はNULL、コンストラクターでループを明示的に使用するように各エントリを設定することです。また、割り当てられたエントリを解放するためのデストラクタも必要になります。これにより、deleteメモリ リークが発生し、メモリ リークが発生しなくなります。これは、リークが悪いためです。

しかし、興味深い質問は、なぜそれが好きなのかということです。次のように単純にバケットを宣言しないのはなぜですか。

HashEntry Table[100];

そうすれば、すべてのバケットがオブジェクトの一部として割り当てられ、バケットの動的な割り当てと割り当て解除、ポインターのチェックなどHashについて心配する必要がなくなります。NULL

これを行う際の問題の 1 つは、HashEntryコンストラクターにint引数が必要なことです。なぜその議論が必要なのかは不明です。必要ないと思いますので、削除してください。

この1 つの変更により、コードが大幅に簡素化され、3 つのバグとクラッシュが解消されます。

于 2013-04-02T16:28:08.583 に答える