【问题标题】:How to optimize my hashtable to reduce real world running time?如何优化我的哈希表以减少现实世界的运行时间?
【发布时间】:2016-08-18 05:56:19
【问题描述】:

下面是我的一段程序,它使用哈希表将文件(字典)加载到内存中。该词典每行仅包含 1 个单词。但是这个过程花费了太多时间。如何优化它??

 bool load(const char* dictionary)
{
    // TODO
    int k;
    FILE* fp = fopen(dictionary,"r");
    if(fp == NULL)
        return false;

    for(int i=0; i<26; i++)
    {
        hashtable[i] = NULL;
    }

    while(true)
    {
        if(feof(fp))
            return true;

        node* n = malloc(sizeof(node));

        n->pointer = NULL;

        fscanf(fp,"%s",n->word);

        if(isalpha(n->word[0]))
        {
            k = hashfunction(n->word);
        }

        else return true;

        if(hashtable[k] == NULL)
        {
            hashtable[k] = n;
            total_words++;
        }

        else
        {
            node* traverse = hashtable[k];
            while(true)
            {
                if(traverse->pointer == NULL)
                {
                    traverse->pointer = n;
                    total_words++;
                    break;
                }
                traverse = traverse->pointer;
            }
        }

    }
   return false; 
}

【问题讨论】:

  • 文件中有多少字(行)? hashfunction 是做什么的?您是否尝试过增加存储桶的数量以便不需要那么多列表遍历?但最重要的是,您是否尝试过使用 profiler 来找出瓶颈所在?
  • 与您的问题无关,但您的阅读循环与while (!feof(fp))which is wrong 没有太大区别。
  • 这是“工作”代码。如果您想了解如何使其“更好”,请在codereview.stackexchange.com 上发布此内容。这样做时,你应该包括你的哈希函数和驱动程序代码,以及你正式测试它的任何方式的注释和测量。
  • @WhozCraig 这不是完整的代码,所以这里或那里都无法回答。

标签: c time hashtable


【解决方案1】:

摆脱潜在的功能问题,然后担心性能。

A) for(int i=0; i&lt;26; i++) 可能是错误的,hashtable[] 定义未发布。使用这么小的固定表肯定是不明智的。

B) "%s"gets() 一样安全 - 两者都不好。使用fgets(),而不是fscanf(fp,"%s",n-&gt;word);

C) 检查来自fscanf()/fgets() 的返回值,而不是if(feof(fp))

D) isalpha(n-&gt;word[0]) --> isalpha((unsigned char) n-&gt;word[0]) 以应对负面的char 值。

E) 检查内存分配失败。

F) 其他问题也可能存在,具体取决于未发布的代码。

然后形成一个简单的测试用例并使用最少的代码工作,考虑在 codereview.stackexchange.com 上发布以征求性能改进。

【讨论】:

【解决方案2】:

您假设文件中的所有单词都是不同的。对于字典来说,这是一个合理的假设,但它是不好的防御性编程。你应该总是假设输入是为了得到你,这意味着你不能对它做任何假设。

但是,在这种情况下,您可能会争辩说哈希表中重复的单词不会阻止它工作;他们只是稍微放慢速度。由于错误的输入不会导致错误、未定义的行为或其他灾难,因此记录引用词是唯一的要求是勉强可以接受的。

无论如何,如果您实际上并未检查重复项,则无需为每次插入遍历整个哈希桶。如果您在存储桶的开头而不是末尾插入新条目,则可以避免扫描,如果存储桶很大,扫描可能会产生明显的加速。

当然,这种优化只能在加载字典时使用。初始化完成后,它不会帮助您使用哈希表,而且很少值得对启动代码进行超优化。

【讨论】:

    猜你喜欢
    • 2013-05-11
    • 2023-03-03
    • 1970-01-01
    • 2020-02-10
    • 2021-01-25
    • 2013-08-20
    • 2019-12-14
    • 1970-01-01
    • 2021-07-22
    相关资源
    最近更新 更多