实现二次探测&链接 - 搜索词典

时间:2016-11-15 18:52:41

标签: c algorithm hash hashtable

我有一些关于我需要做的任务的问题。看起来我正在寻找的是获取代码,然而,我想要做的是学习,因为经过数周的搜索信息后我失去了。 I m really new at C`。

这是作业:

  • 鉴于3个文件(foo.txtbar.txtfoo2.txt),它们都有不同的字数(我需要使用动态内存)。

创建一个要求单词的程序,并告诉您该单词是否在任何文档中(结果是文档的名称)。

示例:

  • 请输入一个词:dog
  • "狗"在foo.txt和bar.txt

(我想我需要加载3个文件,创建一个哈希表,其中包含文档中每个单词的键值,但也有一些东西告诉你哪个是单词所在的文档)。

我想我需要实施:

  • 将{1}转换为Hash Function
  • HashValue
  • 存储每个单词的Hash Table的{​​{1}}(但我认为我还应该存储文档索引?)。
  • 使用HashValue
  • 在我将值插入哈希表时检查dynamic allocation(使用collisionsQuadratic Probing)。
  • 此外,我需要知道正在寻找的单词出现在文本中的次数。

我一直在搜索hashmaps实现,哈希表,二次探测,字符串的哈希函数......但是我现在的头脑很乱,我现在不应该从哪里开始。

到目前为止我读过:

Algorithm to get a list of all words that are anagrams of all substrings (scrabble)?

Implementing with quadratic probing

Does C have hash/dictionary data structure?

https://gist.github.com/tonious/1377667

hash function for string

http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)HashTables.html?highlight=(CategoryAlgorithmNotes)

https://codereview.stackexchange.com/questions/115843/dictionary-implementation-using-hash-table-in-c

提前抱歉我的英语。

希望你能帮助我。

感谢。

第一次编辑

  • 感谢您的快速回复。
  • 我试图把所有东西放在一起尝试一些东西,但@ Shasha99我不能使用Chaining数据结构,我检查你给我的链接。
  • @MichaelDorgan感谢你为初学者发布了一个解决方案但是我必须使用Hashing(它是算法和结构类的),老师告诉我们我们必须实现一个Hash函数,Hash Table以及可能存储重要的另一个结构信息。

思考了一个小时后,我尝试了以下方法:

  • 一种结构,用于存储单词,出现的文档数量以及这些文档的索引。
TRIE
  • 初始化该结构的功能
    typedef struct WordMetadata {
        char* Word;
        int Documents[5];
        int DocumentsCount;
    } WordMetadata;
  • 一个函数,用于加载内存3个文档并索引哈希表中的每个单词。

  • 索引上述结构中的单词的函数

  • 使用二次探测搜索特定单词的功能(如果我解决这个问题,我将尝试使用链接...)。

  • 计算单词哈希值的函数(我想我会使用 void InitTable (WordMetadata **Table) { Table = (WordMetadata**) malloc (sizeof(WordMetadata) * TABLESIZE); for (int i = 0; i < TABLESIZE; i++) { Table[i] = (WordMetadata*) NULL; } } 或我在http://www.cse.yorku.ca/~oz/hash.html找到的任何一个)但是现在:

    < / LI>
djb2

编辑2

我试图实现一些东西,它没有用,但会看看并告诉我出了什么问题(我知道代码是一团糟)

编辑3

这段代码正在编译和运行,但是,有些单词没有找到(可能没有索引我不知道),我正在考虑转移到我在第一条消息中提到的另一个哈希函数。 / p>

  • 程序正确找到每个文本文件中大约85%的单词(每个大约200个单词)。

  • 其他的是ramdom单词,我认为没有正确索引或者我的搜索功能有错误...

这是当前(全功能)代码:

 int Hash (char *WordParam) {

            for (int i = 0; *WordParam != '\0';) {

                i += *WordParam++;

            }

            return (i % TABLESIZE);}

2 个答案:

答案 0 :(得分:1)

我建议您使用TRIE数据结构来存储内存中所有三个文件中的字符串,因为Hash会占用更多空间。 作为第一步,您应该逐个阅读所有三个文件,对于file_i中的每个单词,您应该执行以下操作:

  1. 如果TRIE中已存在该单词,则将文件索引附加到该节点或更新相对于该特定文件的单词计数。在每个节点上,file1,file和file3可能需要3个变量来存储字数的值。
  2. 如果该单词不存在,请在TRIE节点中添加单词和文件索引。
  3. 完成构建TRIE后,检查单词是否存在将是O(1)操作。

    如果你要使用哈希表,那么:

    1. 您应该从how to get hash values for strings.
    2. 开始
    3. 然后阅读open addressing, probingchaining
    4. 然后了解开放式寻址和链接方法中的问题。
    5. 如何使用开放寻址和探测删除哈希表中的元素? here
    6. 如果要进行链接,将如何执行搜索? here
    7. 使用开放寻址制作动态哈希表?摊销分析herehere
    8. 比较链接和开放寻址。 here.
    9. 考虑如何解决这些问题。可能是TRIE?
    10. 您的编辑代码2中的问题:

      您身边的杰出进展!!!

      快速浏览后,我发现了以下问题:

        

      不要使用gets()方法,而是使用fgets()代替:

      gets(Line);
      
           

      以下内容:

      fgets(Line,100,stdin);
      Line[strlen(Line)-1]='\0'; //fgets stores newline as well. so removing newline.
      
        

      该行:

      if ( j < HashTable[j]->DocumentsCount-1){
      
           

      导致分段错误。我想您想访问HashTable[i]

      if ( j < HashTable[i]->DocumentsCount-1){
      
        

      在行中:

           

      HashTable[ActualPosition]->Documents[HashTable[ActualPosition]->DocumentsCount];

           

      你应该分配一些价值。可能是这样的:

           

      HashTable[ActualPosition]->Documents[HashTable[ActualPosition]->DocumentsCount] = DocumentIndex;

        

      Malloc返回void指针。你应该把它投到适当的   之一:

           

      HashTable[ActualPosition] = (TTable*)malloc (sizeof(TTable));

           

      在Hash中创建新节点时,您还应该使用默认值初始化Documents数组:

           

      for(j=0;j<5;j++)HashTable[ActualPosition]->Documents[j]=-1;

        

      找到后,您将从HashTable删除所有内容   用户给出的第一个字。可能是你想把那些代码放在外面   while循环。

           

      你的while循环while(1)没有任何终止条件,你   应该有一个。

      一切顺利!!!

答案 1 :(得分:0)

对于学校作业,您可能不需要担心散列。对于第一遍,你可以改为直接线性搜索:

  1. 创建3个指向char数组的指针(如果愿意,可以创建char **),每个字典文件一个。
  2. 扫描每个文本/词典文件以查看其中包含多少单个词。根据文件的格式,这可能是空格,字符串,换行符,逗号等。基本上,计算文件中的单词。
  3. 在每个文件中分配char *次字数统计数组,并将其存储在该文件的char **中。 (如果在文件中找到100个单词,num_words = 100; fooPtr = malloc(sizeof(char *) * num_words);
  4. 第二次返回文件,并将字符数组分配给文件中每个单词的大小,并将其存储在先前创建的数组中。现在,每个字典文件中的每个单词都有一个“锯齿状的2D数组”。
  5. 现在,您的词典有3个数组,可以使用它们直接扫描单词。

    当给出一个单词时,设置一个for循环来查看每个文件的char数组。如果输入的单词与当前扫描的字典匹配,则表示您找到了匹配项并应打印结果。扫描完所有词典后,就完成了。

    让事情更快的事情:

    1. 对每个字典进行排序,然后您可以二进制搜索匹配项(O(log n))。
    2. 创建一个哈希表并将每个字符串添加到其中以进行O(1)查找时间(这是大多数专业解决方案所做的,这就是为什么你在这上面找到了很多链接。)
    3. 我这里几乎没有提供任何代码,只是一种方法。试一试。

      最后一点 - 即使您决定使用哈希方法或列表或其他内容,您使用数组编写的代码仍然有用。