[音乐播放] ROB BOWDEN:你好。 我抢。 而且我们这个解决方案了。 所以在这里我们要实现 一个总表。 我们看到,我们的结构节点 表是要这个样子。 因此,这将有一个char字 数组大小长度+ 1。 不要忘了+1,因为最大 字在字典中是45 字符。 然后,我们将需要一个额外的 字符反斜杠零。 然后我们在每个哈希表 斗将要存储 节点链表。 我们没有做线性探测在这里。 所以为了链接到下一个 在桶的元素,我们需要一个 结构节点*未来。 确定。 所以,这就是一个节点的样子。 现在,这里是声明 我们的哈希表。 这将有16,834桶。 但这个数字其实并不重要。 最后,我们将有 全局变量哈希表大小,这 会作为零开始。 并且它会跟踪如何 许多词都在我们的字典。 因此,让我们来看看负荷。 请注意,负载,它返回一个布尔值。 您将返回true,如果它是成功的 加载,否则返回false。 它需要一个为const char *的字典, 这就是词典 我们要打开。 所以这是第一件事情 我们要做的。 我们要去给fopen的 字典阅读。 而我们将不得不作出 确保它成功了。 所以,如果它返回NULL,那么我们没有 成功打开词典。 我们需要返回false。 但假设它确实成功 开放的,那么我们要读取的 字典。 因此,保持循环,直到我们找到了一些 理由打破这种循环, 我们将拭目以待。 因此,保持循环。 现在我们要 malloc的一个节点。 ,当然,我们需要 宣扬再次检查。 所以,如果mallocing没有成功,那么 我们要卸载的任何节点,我们 碰巧的malloc之前,请关闭 字典和返回false。 但是忽略了,假设我们 成功了,那么我们要使用的fscanf 从读一个字我们 字典到我们的节点。 所以请记住该条目>字是字符 大小茸,加1字缓冲区 那我们要存储的单词英寸 所以的fscanf会返回1,只要 因为它能够成功地 从文件中读一个字。 如果任何一个错误发生,或者我们 到达文件的结尾,它 将不会返回1。 在这种情况下,它不会返回1, 我们终于要摆脱 这个while循环。 所以我们看到,一旦我们成功 读一个字到 入门>字,那么我们也要去那 词使用我们的哈希函数。 让我们来看看 散列函数。 所以,你并不真的需要 要理解这一点。 而实际上我们只是拉着这个散列 从互联网上起作用。 你需要认识到的唯一一件事就是 这需要为const char *字。 所以它采取一个字符串作为输入,并 返回一个unsigned int作为输出。 所以这就是所有的散列函数,它是 需要在输入和给你一个 索引的哈希表。 请注意,我们被NUM_BUCKETS模变, 使返回值 实际上是一个索引哈希表 并没有索引超出了 阵列的界限。 所以,有了该功能,我们将 散列,我们读单词 字典。 然后我们将使用 散列插入 进入哈希表。 现在,哈希表散列是当前 链接表列表中。 而且它很可能 它只是为NULL。 我们要插入我们在入口 开始这个链表中。 所以我们就要有我们目前的 切入点是什么哈希表 目前指向。 然后我们要保存, 在哈希表在 哈希,当前条目。 所以,这两条线插入成功 在本月初的入口 链表的索引处 在哈希表。 一旦我们与该做的,我们知道 我们发现了另一个字的 字典,我们增加了。 因此,我们继续这样做,直到的fscanf 最后在返回的东西非1 这一点请记住, 我们需要自由进入。 所以,在这里我们malloced一个条目。 我们试着读的东西 从字典。 我们没有成功地读 东西从字典中,在 我们需要释放进入这种情况下, 我们从来没有真正投入 哈希表,并最终破裂。 一旦我们突破了,我们需要看到的,好了, 我们没有打出来,因为有 从文件中读取的错误? 还是我们打出来,因为我们 到达文件的末尾? 如果有错误,则 我们要返回false。 由于负载没有成功。 而在这个过程中,我们要卸载 所有我们在阅读的话, 关闭字典文件。 假设我们没有成功,那么我们就 仍然需要关闭字典 文件,最后返回true,因为我们 成功加载字典。 这就是它的负载。 所以,现在检查,给定一个哈希表装, 是要这个样子。 因此,检查,它返回一个布尔值,它是 将指示是否通过 以char *的话,是否通过 字符串是在我们的字典。 因此,如果它是在字典中, 如果是在我们的哈希表中, 我们将返回true。 如果不是的话,我们将返回false。 鉴于这种通过在Word中,我们 要哈希的话。 现在认识到的重要一点是 在负载,我们知道,所有的 也就是说,我们要为小写。 但在这里,我们不是那么肯定。 如果我们看一看我们的哈希函数, 我们的哈希函数实际上 是下壳体的每个字符 的话。 所以不管资本化 总之,我们的哈希函数是返回 同样的指数无论 资本化,因为这将有 返回一个完全小写 版的字。 好吧。 这是我们的指数进入 哈希表这个词。 现在,这个for循环是要 遍历链表 这是该索引。 所以请注意,我们初始化入口 指向该索引。 我们将继续 而进入!= NULL。 请记住,更新指针 在我们的链接列表条目=项目>未来。 因此,有我们目前的切入点 在链表中的下一个项目。 因此,对于在该链接的表的每个条目, 我们将使用strcasecmp。 这不是STRCOMP。 因为再次,我们要 做事不区别大小写。 因此我们使用strcasecmp比较 这是通过这个词通过 对词功能 那就是在这个条目。 如果返回零,这意味着有 一个匹配,在这种情况下,我们希望 返回true。 我们成功地找到了 字在我们的哈希表。 如果有不匹配,那么我们 再次要循环,并期待在 下一个条目。 我们将继续循环,同时有 在此链表条目。 如果我们分手会发生什么 出这个for循环? 这意味着我们没有发现一个条目, 匹配这个词,在这种情况下, 我们返回false,表明我们的 哈希表中没有包含这个词。 ,这是一个检查。 因此,让我们来看看大小。 现在,大小将是非常简单的。 因为记得在负载,每个字 我们发现,我们增加一个全球性的 可变的哈希表大小。 因此,大小功能只是去 返回全局变量。 就是这样。 现在,终于,我们需要卸载 字典曾经的一切的完成。 那么我们如何做到这一点? 在这里我们要遍历 本表的所有桶。 因此,有NUM_BUCKETS桶。 并为每个链表我们 哈希表,我们将遍历 该链接的表的全部, 释放每个元素。 现在,我们必须要小心。 所以在这里,我们有一个临时变量 这是存储指针指向下一个 元件中的链表。 然后我们将免费 当前元素。 我们需要确保我们做到这一点,因为我们 不能只释放当前元素 然后再试着访问下一个指针, 因为一旦我们释放它, 内存变为无效。 因此,我们需要保持周围的指针 下一个元素,那么我们就可以释放 当前元素,然后我们就可以更新 我们目前的元素指向 下一个元素。 我们将循环而有元素 在此链表。 我们将做到这一点的所有链接 在哈希表中列出。 有一次,我们正在与该做的,我们已经 彻底卸载的哈希表,并 我们就大功告成了。 所以这是不可能的卸载 永远返回false。 而当我们完成后,我们 刚刚返回true。 让我们给这个方案一试。 因此,让我们来看看我们什么 结构节点的样子。 在这里,我们看到,我们就要有一个bool 字和一个结构节点*儿童 支架字母。 所以,你可能是第一件事情 想知道,为什么是字母 编辑定义为27? 好了,记住,我们将需要 待处理的单引号。 所以这将是有点的 整个程序中的特殊情况。 现在还记得如何在特里 实际工作。 比方说,我们正在索引字 “猫”。然后从字典树的根, 我们要看看孩子 数组,我们要看看 对应于字母索引 C.这样会被索引2。 因此考虑到,那将 给我们一个新的节点。 然后我们将努力从该节点。 所以,有了这个节点,我们再次 去看看孩子们的数组。 而且我们要看看指数为零 对应于猫在A。 这样的话,我们会去到该节点, 并给予该节点我们将 来看看它到底是一个对应 到T和移动到该节点, 最后,我们已经完全看 通过我们的词“猫”。现在bool的 单词应该以指示是否 这个给定的字实际上是一个字。 那么,为什么我们需要这种特殊情况? 什么样的词以及“灾难” 是在我们的字典,但 单词“猫”是不是? 所以,看,看单词“猫” 在我们的字典,我们 要成功地去翻 该指数C-A-T的区域节点。 但是,这仅仅是因为灾难 发生在其上创建节点的方法 从C-A-T,一路 字的结尾。 所以布尔字被用来指示是否 这个特殊的位置 实际上表示一个字。 好的。 所以,现在我们知道它特里是什么 会是什么样子,让我们来看看 加载功能。 因此,负载将会返回一个bool 对于我们是否成功 不成功地加载的字典。 这将是字典 我们要加载。 我们是这样做的第一件事就是打开 了那本词典阅读。 我们必须确保 我们没有失败。 因此,如果在字典不 成功打开,它将返回 null,在这种情况下,我们 要返回false。 但假设它成功 开了,那么我们就可以真正阅读 通过字典。 我们将这样的第一件事 想要做的是我们有这个 全局变量的根。 现在根将是一个节点*。 这是我们的字典树的顶部,我们是 将要逐一查看。 所以我们要去的第一件事 想要做的是分配 内存为我们的根。 请注意,我们使用了释放calloc 功能,这是基本相同 作为malloc函数,除了它的 保证返回的东西是 完全归零。 因此,如果我们使用的malloc,我们需要 通过所有的指针我们 节点,并确保 它们都是空。 所以释放calloc会替我们。 现在,就像malloc的,我们需要做 确保分配竟是 成功的。 如果返回null,那么我们 需要关闭或字典 文件并返回false。 所以,假设分配是 成功,我们将使用一个节点* 游标遍历我们的线索。 所以,我们的根永远不会改变, 但我们要使用光标 实际上去从一个节点到另一个节点。 因此,在这个for循环,我们正在阅读 通过字典文件。 而我们使用的是龟etc。 龟etc是要抢单 字符从该文件。 我们要继续抓 虽然我们不到达的字符 该文件的末尾。 有两种情况,我们需要处理。 第一,如果字符 是不是一个新行。 所以我们知道,如果它是一个新行,然后 我们即将进入到一个新词。 但假设它不是一个新行,然后 在这里,我们想弄清楚的 指数我们要索引 在孩子阵列 我们看着面前。 所以,就像我之前说的,我们需要 特殊情况下的单引号。 我们正在使用的三元通知 运营商在这里。 所以,我们要读这个,因为如果 我们读到的字符是一个 单引号,那么我们要设置 指数=“字母”-1,这将 是该指数26。 否则,如果它不是一个单引号,有 我们要设置索引 等于c - 一个。 所以请记住先前对套回, C - 一个是要给我们 C的英文字母位置所以,如果 C是字母A,这将 给我们指数为零。 对于字母B,它会给 我们的索引1,依此类推。 因此,这给了我们中的索引 儿童阵列,我们想要的。 现在,如果该指数是目前在空 子,这意味着,一个节点 目前不存在 从该路径。 因此,我们需要分配 一个节点的路径。 这就是我们在这里做的。 所以,我们要再次使用释放calloc 功能,这样我们就不必 零出所有的指针。 而我们又需要检查 这释放calloc没有失败。 如果释放calloc会失败,那么我们就需要 卸载一切,我们关闭 字典,并返回false。 因此,假如它没有出现故障,则 这将创建一个新的子我们。 然后我们会去那个孩子。 我们的光标会遍历 下到那个孩子。 现在,如果这不是空,首先, 然后将光标可以只遍历 下到那个孩子没有实际 不必分配任何东西。 这是我们第一次发生的情况 分配单词“猫”。和 这意味着当我们去分配 “大灾难”,我们并不需要创建 再次为C-A-T的节点。 他们已经存在。 这是什么东西? 这是其中c是条件 反斜杠N,其中c是一个新行。 这意味着我们已经成功 完成了一个字。 现在,我们究竟想要做的,当我们 成功地完成了一个字? 我们将用这个词场 我们的内部结构的节点。 我们要设置为true。 以便表明该节点 表示成功 一句话,一个实际的单词。 现在设置为true。 我们要重设我们的光标点 在特里的开始了。 最后,增加我们的字典 大小,因为我们发现了另一个工作。 所以,我们要继续这样做, 在读取一个字符一个字符, 构建新的节点在我们的线索和 每个字在字典中,直到 我们终于到达C!= EOF,其中 情况下,我们打出来的文件。 现在有下2箱子 我们可能EOF打击。 如果有错误,首先是 读取该文件。 所以,如果有错误,我们 需要做的典型。 卸载一切,接近 该文件,返回false。 假设没有了一个错误,该 只是意味着我们实际上打的结尾 的文件,在这种情况下,我们关闭 文件,并返回true,因为我们 成功载入字典 进入我们的线索。 所以,现在让我们看看检查。 纵观检查功能,我们看到 该检查将要返回一个bool。 如果这个词,它是返回true 传递是在我们的线索。 它,否则返回false。 那么你是如何判断是否 这个词在我们的线索? 我们在这里看到的是,就像以前一样, 我们将使用游标来遍历 通过我们的线索。 现在,在这里我们要遍历 在我们的整个字。 因此,迭代,我们过去的话, 我们要确定 索引的儿童阵列 对应词支架一所以这 是要完全一样 负载,其中,如果字[I] 是一个撇号,然后我们想 使用索引“字母” - 1。 因为我们确定了 就是我们要去的地方来存储 单引号。 否则我们将使用两个低字 支架一,因此请记住一句话就可以 具有任意大小写。 所以我们要确保我们 用一个事物的小写版本。 然后从'a'到一次减 再次给我们按字母顺序排列 该字符的位置。 所以这将是我们的索引 进入孩子们的数组。 而现在,如果该索引到孩子 数组为null,这意味着我们 不能再继续迭代 下来我们的线索。 如果是这样的话,这个词不能 可能是在我们的线索。 因为如果它是,这将 意味着将有一个路径 下到这个词。 而你永远不会遇到空。 所以遇到空,返回false。 的字不在字典中。 如果它不为null,那么我们 要继续迭代。 所以我们要在那里光标 以指向特定的 节点的索引处。 我们继续在整个这样做 整个单词,假设 我们从不打空。 这意味着我们能够获得通过 整个单词并找到 在我们的尝试的一个节点。 但我们还没有完全完成。 我们不希望只是返回true。 我们要返回游标>字。 由于再次记住,是“猫”不 在我们的字典,和“大灾难” ,那么我们会成功,我们得到 通过字“猫”。但光标 字会是假的,而不是真实的。 所以我们返回游标字来表示 是否该节点实际上是一个字。 就是这样的检查。 因此,让我们看看大小。 所以,大小将是很容易 因为,记得在负载,我们 递增的字典大小 我们遇到的每一个字。 所以,大小只是要 返回字典大小。 就是这样。 所以最后我们已经卸载。 所以卸载,我们将使用 递归函数实际上做 对我们的工作。 因此,我们的功能是要 算得上卸料。 什么是卸载怎么办? 我们在这里看到的卸料器是要 遍历所有的儿童在 这个特殊的节点。 和如果该子节点不是 null,那么我们要 卸的子节点。 因此,这是你递归卸载 我们所有的孩子。 一旦我们确定我们的孩子 已经卸载,那么我们 可以释放自己,所以 卸载自己。 这将递归工作 卸载整个线索。 然后一旦这样做了, 我们可以只返回true。 卸载不能失败。 我们只是释放的东西。 所以一旦我们完成了解放 一切,返回true。 就是这样。 我的名字是罗布。 这是拼写检查。 [音乐播放]