经过仔细考虑,我为您提供以下示例(请注意,您可以翻页并对条目进行排序,因此我建议您将 双向链表误认为是 char[ ] 数组..)
(来源:toastytech.com)
我的原始答案如下(是的,我宁愿找到Microsoft Bob 的屏幕截图,也不愿给你完成作业所需的完整源代码):
好吧,让我们想想关于人的所有有趣的东西:
typedef struct person {
char *firstname;
char *lastname;
char *phone;
struct person *prev;
struct person *next;
unsigned fname_hash;
unsigned lname_hash;
unsigned full_name_hash;
} person_t;
注意名字、姓氏和全名的哈希值,这是人们通常搜索地址簿的方式。
然后看看一个非常非常基本的哈希算法(直接从 ini 文件解析器中提取出来(基本上只是一个字典)that I maintain):
unsigned simple_hash(char *key)
{
int len;
unsigned hash;
int i;
len = strlen(key);
for (hash = 0, i = 0; i < len; i++) {
hash += (unsigned) key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
上面的哈希函数不是防碰撞的。当你认为你有匹配时,你仍然需要比较字符串,以确保。但是,使用该哈希(或其他)是搜索链表的最快方法。您将比较无符号值,而不是字符串(当然,除非哈希匹配,然后您比较只是为了检查以确保它不是冲突)。
开始时,为列表中的 n 个条目分配足够的空间(3 - 4 应该没问题)。之后,您需要为每次添加或删除重新分配。
当然,大多数人希望他们的地址簿按字母顺序显示,因此插入和删除节点只是成功的一半。您还需要对列表进行排序。很难用你提供的东西来帮助你。
我可以说的是通讯录通常包含公司信息,因此您可能会遇到“1A Pest Control”。在这种情况下,您可能想查看natural language string comparison。
最后,如果这必须适用于宽字符集,您需要编辑并重新标记您的问题。