CS50拼写检查器哈希表实现代码求评:方向是否正确?
CS50 Speller 字典加载代码审核与修正建议
整体方向判断
你的实现思路是对的:用哈希表+链表解决冲突,选26³=17576个桶的设计符合项目常规思路,头插法也能保证插入效率,框架逻辑没问题。
代码里的问题和修正点
- 字符串存储没必要用数组:你写的
string word_from_dictionary[1];完全多余,直接用char word_from_dictionary[LENGTH + 1];就行——LENGTH是项目定义的单词最大长度,这样能刚好容纳最长单词,避免越界风险。 - 空指针访问会崩溃:初始化哈希表时你把
table[i]设成了NULL,但后面判断table[index]->next == NULL是直接访问NULL指针的成员,这会导致程序崩溃。正确逻辑应该是判断table[index]本身是否为NULL:- 如果
table[index]是NULL,直接让它指向新节点 - 如果不是NULL,用头插法把新节点放在链表最前面
- 如果
- 没检查内存分配失败:
malloc可能返回NULL(内存不够时),你没做判断,后续strcpy会直接崩溃,必须加检查。 - 未使用变量冗余:
count_words_uploaded定义后没用到,要么删掉,要么用来统计加载的单词数(后续size函数可以复用这个计数)。
修正后的完整代码
// 哈希表节点结构 typedef struct node { char word[LENGTH + 1]; struct node *next; } node; // 哈希表桶数量:26³=17576 const unsigned int N = 17576; // 哈希表数组 node *table[N]; // 加载字典到内存,成功返回true,失败返回false bool load(const char *dictionary) { FILE *file = fopen(dictionary, "r"); if (file == NULL) { printf("无法打开文件\n"); return false; } char word_from_dictionary[LENGTH + 1]; // 初始化哈希表所有桶为NULL for (int i = 0; i < N; i++) { table[i] = NULL; } while (fscanf(file, "%s", word_from_dictionary) != EOF) { int index = hash(word_from_dictionary); // 分配节点内存并检查是否成功 node *n = malloc(sizeof(node)); if (n == NULL) { fclose(file); printf("内存分配失败\n"); return false; } strcpy(n->word, word_from_dictionary); n->next = NULL; // 头插法插入节点 if (table[index] == NULL) { table[index] = n; } else { n->next = table[index]; table[index] = n; } } fclose(file); return true; }
额外提示
- 你的
hash函数要处理好单词长度不足3的情况,比如单个字母的单词,按前三个字母(不足的补0)计算索引,公式可以参考(tolower(word[0])-'a')*26*26 + (tolower(word[1])-'a')*26 + (tolower(word[2])-'a')(记得先转小写,因为字典里的单词可能有大写)。 - 测试时先用CS50提供的小字典(比如
small)验证功能,再用大字典(比如large)测试性能。
内容的提问来源于stack exchange,提问作者antonio nobrega
相关产品推荐
相关产品推荐

