CS50 Week5 Speller编译正常但结果异常,check耗时过长
CS50 Speller 性能与功能问题修复
核心性能问题:哈希表设计缺陷
1. 桶数过少导致链表过长
当前哈希表仅设置26个桶(const unsigned int N = 26),14万+字典单词会被强制分配到26个链表中,平均每个链表承载5000+节点。check函数遍历长链表的时间成本会直接拉满,这是耗时8.41秒的核心原因。
建议大幅增加桶数,比如设置为const unsigned int N = 65536;或至少1000以上,从根源减少每个桶的节点数量。
2. 哈希函数存在未初始化变量+低效问题
哈希函数中int value;未初始化,会导致计算时使用随机垃圾值,最终哈希结果完全不可控,进一步加剧链表冲突。同时仅简单累加字符值的哈希方式冲突率极高,无法有效分散节点。
修复后的哈希函数示例:
unsigned int hash(const char *word) { unsigned long value = 0; const unsigned int prime = 31; for (int j = 0; word[j] != '\0'; j++) { value = value * prime + tolower(word[j]); } return value % N; }
- 初始化
value为0,避免垃圾值干扰 - 使用素数乘法哈希逻辑,大幅降低冲突概率
功能错误:Unload函数逻辑漏洞
当前unload函数在释放第一个桶的内存后就直接return true;,剩余25个桶的内存完全未释放,存在严重内存泄漏。正确逻辑需遍历所有桶,确认全部释放后再返回成功:
bool unload(void) { for (int j = 0; j < N; j++) { node *cursor = table[j]; while(cursor != NULL) { node *temp = cursor; cursor = cursor->next; free(temp); } } return true; }
潜在风险:全局变量滥用
全局变量counter和i容易引发逻辑冲突(比如load和check同时操作i),建议改为局部静态变量或函数内定义:
- 在
load函数内定义static unsigned int counter = 0;,替代全局counter - 在
check和load函数内单独定义unsigned int i;,避免全局变量污染
修复后效果验证
调整哈希表配置与函数逻辑后,check函数的遍历耗时会大幅降低,unload也能正确释放所有内存,不会再出现内存泄漏问题。
内容的提问来源于stack exchange,提问作者asdfghjkl
相关产品推荐
相关产品推荐

