ROB BOWDEN:你好。 我抢,让我们散 这个解决方案了。 所以在这里我们要实现 一般的哈希表。 我们看到,我们的散列的结构节点 表是要这个样子。 因此,这将有一个char字 数组大小长度加1。 不要忘了,因为最大的1 字在字典中是45 字符,然后我们要 需要一个额外的字符 反斜杠0。 然后在我们的每一个哈希表 斗将要存储 节点链表。 我们没有做线性探测在这里。 所以为了链接到下一个 在桶的元素,我们需要一个 结构节点*未来。 所以,这就是一个节点的样子。 现在,这里是声明 我们的哈希表。 这将有16,384桶,但 这个数字其实并不重要。 最后,我们将有 全局变量hashtable_size,这 即将为0开始关闭,它的 要跟踪多少字 是在我们的字典。 好的。 因此,让我们来看看负荷。 所以请注意,负载, 它返回一个布尔值。 您将返回true,如果它是成功的 加载,否则为false。 它需要一个为const char *星级 字典,它是词典 我们要打开。 所以这是第一件事情 我们要做的。 我们要去给fopen的字典 读,我们将有 以确保它成功,所以如果 它返回NULL,那么我们就没有 成功打开词典 我们需要返回false。 但假设它确实成功 开放的,那么我们要读取的 字典。 因此,保持循环,直到我们找到了一些 理由打破这种 循环,我们拭目以待。 因此,保持循环,现在我们要去 将malloc的单个节点。 当然,我们需要错误检查 再所以,如果mallocing没有成功 我们要卸载的任何节点,我们 碰巧的malloc之前,请关闭 字典和返回false。 但是忽略了,假设我们 成功了,那么我们要使用的fscanf 从读一个字我们 字典到我们的节点。 因此请记住入门>字是字符 大小长度的字缓冲区加 一个我们要去 字存储英寸 所以的fscanf会返回1,只要 因为它能够成功读取 字从该文件。 如果任何一个错误发生,否则我们到达 该文件的结束时,它不会 返回1在这种情况下,如果它不 返回1,我们终于要打破 出这个while循环的。 所以我们看到,一旦我们成功 读一个字到 入门>字,那么我们将散列 使用我们的哈希函数这个词。 让我们来看看 散列函数。 所以,你并不真的需要 要理解这一点。 而实际上,我们只是拉这 从互联网散列函数。 你需要认识到的唯一一件事就是 这需要为const char *的话, 所以它采取一个字符串作为输入,并 返回一个unsigned int作为输出。 所以这就是所有的散列函数,它是 发生在一个输入,它给你一个 索引的哈希表。 请注意,我们通过NUM_BUCKETS改装 所以返回的哈希值 实际上是一个索引,哈希表 并没有索引超出了 阵列的界限。 因此,考虑到哈希函数,我们将 散列,我们读单词 从字典中,然后我们要去 使用具有插入 进入哈希表。 现在,哈希表散列是当前 链表哈希表中,并 这是非常可能的,仅仅是NULL。 我们要插入我们在入口 开始这个链表,等等 我们将有我们的当前条目 指向什么样的哈希表现 点,然后我们要存储 在哈希哈希表中 当前条目。 所以,这两条线插入成功 在本月初的入口 链表的索引处 在哈希表。 一旦我们与该做的,我们知道 我们发现了另一个字的 字典和我们增加了。 因此,我们继续这样做,直到的fscanf 最后返回非的东西在1 这一点请记住,我们需要 免费入场,所以在这里,我们malloced的 进入我们试着读的东西 从字典。 我们没有成功地读 从字典的东西在其中 情况下,我们需要释放进入我们 从来没有真正投入到哈希表 终于攻破。 一旦我们突破了,我们需要看到,好了, 我们没有打出来,因为有 从该文件中读出错误,或 我们没有打出来,因为我们到达 该文件的末尾? 如果出现了错误,那么我们要 返回false,因为负载没有 成功,并在这个过程中,我们要 卸载所有我们读的话 在并关闭字典文件。 假设我们没有成功,那么我们就 仍然需要关闭字典 文件,最后返回,因为真正的 我们已经成功地加载了 字典。 这就是它的负载。 所以,现在检查,给出一个加载哈希表, 是要这个样子。 因此,检查时,它返回一个布尔值,它 将要指示是否 传入的​​char *的话,是否 传入的​​字符串是在我们的字典。 因此,如果它是在字典中,如果是 在我们的哈希表,我们将返回 真的,如果不是的话, 我们将返回false。 鉴于这种传入的字,我们 要哈希的话。 现在,认识到一个重要的事情是 在负载时,我们知道,所有的 的话打算是小写, 但在这里,我们不是那么肯定。 如果我们看一看我们的哈希函数, 我们的哈希函数实际上 是小写的每个字符 的话。 所以不管资本化 总之,我们的哈希函数是要 返回相同的指数无论 资本是因为它会 返回一个完全小写 版的字。 好的。 所以这是我们的索引。 这是这个词的哈希表。 现在,这个for循环是怎么回事 过度链表 这是该索引。 所以请注意,我们初始化入口 指向该索引。 我们将继续,而不会进入 不等于NULL,并且记住, 更新指针在我们的链表 入门等于入门>下一个,所以有 我们目前的入口点 在链表中下一个项目。 好的。 因此,对于在该链接的表的每个条目, 我们将使用strcasecmp。 这不是strcmp函数,因为我们再次 想要做的事情的情况下不区分大小写。 因此我们使用strcasecmp比较字 被传递给这个函数 对词 在这个条目。 如果返回0,这意味着有 一个匹配,在这种情况下,我们希望 返回true。 我们成功地找到了 字在我们的哈希表。 如果有不匹配,那么我们 再次要循环,并期待在 下一个条目。 我们将继续循环,同时有 在此链表条目。 如果我们分手会发生什么 出这个for循环? 这意味着我们没有发现一个条目, 匹配这个词,在这种情况下, 我们返回false,表明我们的 哈希表中没有包含这个词。 就是这样的检查。 好的。 因此,让我们来看看大小。 现在,大小将是非常简单的 因为记得在负载,每个字 我们发现,我们增加一个全球性的 变量hashtable_size。 因此,大小的功能仅仅是 要返回全球 变量,就是这样。 现在,终于,我们需要卸载 字典曾经的一切的完成。 那么我们如何做到这一点? 在这里,我们遍历所有 我们的哈希表的桶。 因此,有NUM_BUCKETS桶。 并为每个链表在我们的散列 表中,我们要遍历所有的 链表的全部 释放每个元素。 现在,我们需要小心,所以在这里我们 有一个临时变量,它是 存储指针指向下一个 元件中的链表。 然后我们将免费 当前元素。 我们需要确保我们做到这一点,因为我们 不能只释放当前元素 然后再试着访问下一个指针 因为一旦我们释放它 内存变为无效。 因此,我们需要保持周围的指针 下一个元素,那么我们就可以释放 当前元素,然后我们就可以更新 我们目前的元素指向 下一个元素。 我们将循环而有元素 在此链表。 我们将做到这一点的所有链接的列表中 哈希表,有一次我们就大功告成了 这样,我们已经完全卸载 哈希表,我们就大功告成了。 所以这是不可能卸载到永远 返回false,而当我们完成后,我们 刚刚返回true。