【问题标题】:Designing data structures for an address book in C program?在 C 程序中为地址簿设计数据结构?
【发布时间】:2010-04-25 14:31:01
【问题描述】:

我希望通讯录项目的数量是可变的——事先不知道;我认为使用链表是正确的选择?

"用户可以输入新的人员数据,或打印给定姓名的数据,询问数据不必是姓名,也可以是电话号码上的地址,程序打印有关人员的全部信息,打印书的内容按字母顺序排列。将一些数据存储在一个文件中;在修改后将其检索并保存。

程序应将文件写入磁盘并从中检索文件。应使用参数调用程序。”

我将使用 malloc,但我不知道何时以及如何使用。

请问有人做过类似的任务或有什么想法可以帮助我吗?

【问题讨论】:

  • 到目前为止你有什么? (最好先尝试一下,然后来这里问。这样你会学到更多)。
  • 你能提供更多导致这项任务的讲座细节吗?例如,您是否研究过通过双向链表进行散列/搜索的方法?您的老师是否表达了对某些方法的偏好?有几种方法可以做到这一点,但只有其中一种可能会让你取得好成绩。
  • 老师推荐我使用链表..
  • 知道什么是链表吗?

标签: c


【解决方案1】:

对于“玩具”程序,链表就足够了。链表的问题在于,如果您有很多记录。在更糟糕的情况下,您将不得不搜索整个列表以查找或不查找条目。最好的方法是散列或散列和树的组合。如果您使用指针,则必须使用malloc()。我建议你查看Wikipedia article 关于链表实现。他们甚至有一个 C 的例子。

【讨论】:

    【解决方案2】:

    经过仔细考虑,我为您提供以下示例(请注意,您可以翻页并对条目进行排序,因此我建议您将 双向链表误认为是 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

    最后,如果这必须适用于宽字符集,您需要编辑并重新标记您的问题。

    【讨论】:

    • 为什么使用数组;我希望通讯簿项目的数量是可变的 - 事先不知道 typedef struct person { char firstname[81];字符姓氏[81];字符电话[20]; ????
    • @osabri,我展示的是一个双向链表,它更多适合存储n个事先不知道的东西。此外,您可以通过各种方式取出、放入、分类。然而,您似乎回想起一个 node (或记录,如果您愿意的话)是整个实现?我不会为你做作业。请阅读链表实际上是什么。提示,array 是一种过分的轻描淡写。
    • @osabri,改变了我的答案。请注意,它仍然是相同的答案。不同之处在于,除了列表及其节点之外,现在您必须分配列表中每个节点(哈希除外)的所有成员。
    • 是的。我Bobbed他。我别无选择。
    【解决方案3】:

    您可以使用链表或双向链表,但条件之一是您可以按排序顺序显示数据。当然,尚不清楚姓氏(姓氏)或名字(名),城镇或......的字母顺序。

    您可能需要使用比列表更适合排序的结构,尤其是在排序标准在不同时间可能不同的情况下。一般来说,对任意单链表进行排序真的很难并不是特别有效,但这里的效率可能并不重要。有一些方法可以对双向链表进行排序更容易排序,这样可以提高效率。您通常会得到一个数组或某种堆或树结构,因为它们可以更有效地排序。

    但是,如果您有一个固定的排序标准,并且可以在构建列表时将项目按顺序排列,那么单链表就可以了。

    您将在创建新条目时使用malloc() - 每个条目可能多次使用。

    当您写入磁盘时,您可能会生成一个文本文件(因为如果文件全是文本,则更容易看到需要修复的内容)。您需要标记每个条目的开头和结尾。

    【讨论】:

    • 为什么对单个链表进行排序很难? Mergesort 对两者都适用,而且对于单个链表更容易,因为您不必关心 prev 指针。
    • @quinmars:好问题。也许我正在考虑一种对其有任意限制的排序(原位排序)。如果从旧列表中拉出下一项并插入到新列表中,则相对容易(效率不高,但足够容易)。我会(再次)调整我的答案。谢谢。
    【解决方案4】:

    实际上链表不会将您的数据存储到硬盘中。您可以使用FILE 来存储数据。您可以查看http://www.utas.edu.au/infosys/info/documentation/C/CStdLib.html 链接以获取小参考。

    【讨论】:

      猜你喜欢
      • 2019-05-20
      • 1970-01-01
      • 2014-09-01
      • 2010-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多