【问题标题】:Two hash tables, hash table with double key or different solution?两个哈希表,双键哈希表还是不同的解决方案?
【发布时间】:2011-01-22 21:07:12
【问题描述】:

再说一次,谈论我即将到来的大学项目...我今天有一节课,我们可以在其中询问有关该项目的信息,但我仍然没有决定最好的方法。

基本上,我有一堆用户(一些结构有几个成员),必须按名称和 SSN 快速搜索。由于我还需要在 Graph 上使用这些用户(用于其他操作),因此我将使用指针。

现在,我想使用两个哈希表。一个键是名称,另一个键是 SSN。但我不喜欢有两个哈希表的想法,只是使用不同的键并指向同一个地方。

我想到了使用带有两个键的哈希表,但我什至不知道这是否可能,我相信不可能。我就是想不出办法,也许有,也许没有。

除了这两个解决方案之外,我想不出任何其他选择......我可能不得不使用两个哈希表。

你们有其他的建议吗?

【问题讨论】:

  • “在图表上使用这些用户”是什么意思?是一次性给定所有用户,然后您必须按名称/SSN 搜索一堆,还是给定一些用户,然后是一些搜索查询,然后是更多用户,然后是更多查询等?
  • 请永远不要使用 SSN 作为密钥 :-(
  • 不要打扰图表部分,这只是意味着我需要使用图表来做其他事情,但我无法向您解释什么,因为我还没有。 @Steven 为什么不呢?关心证明为什么?而且,也许,提供一个替代方案?您如何建议我通过 SSN 快速查找用户?
  • @Nazgulled 由于涉及的复杂性(额外的解密/加密步骤),使用 SSN 作为索引/密钥通常是个坏主意。也就是说,除非您使用未加密的关键个人数据(您永远不会这样做,对吗?)。如果您想通过 SSN 对表进行索引,请在获得 SSN 后立即通过加密哈希运行 SSN(类似 MD5 就足够了)并使用哈希版本进行所有索引等。
  • 您不应该使用 SSN,因为 1) 它们会发生变化(如果发生欺诈,您可以获得新的) 2) 它们被视为私人信息,很难(呃)保护您的主要信息钥匙 3)它们被重复使用(在其前任所有者去世后)

标签: c hashtable key


【解决方案1】:

我会选择两个哈希表。将其视为数据库中的两个索引。数据库是您的用户,您提供两个索引:一个 ssn 索引和一个名称索引。

【讨论】:

  • 这就是我的想法,但困扰我的是,我总是会为同一个用户结构浪费 2 个指针,每个哈希表中都有一个。也许没有办法解决它......
  • 保留两个索引的额外空间应该不是问题,除非您计划存储大量用户。问题是在添加、删除、重命名用户或您计划执行的任何操作时保持索引最新的额外复杂性。如果您认为这很容易处理,那么我会说这是要走的路。
【解决方案2】:

我认为两个 Hashtable 都可以。还可以考虑二叉搜索树,它们可以更紧凑,但 O(log n) 搜索并且更难实现。

“有两个键的哈希表”没听说过……

【讨论】:

  • 我也不是,我只是虽然它可能存在哈哈...我考虑过二叉搜索树,但就像你说的,它们是 O(log n),其中哈希表更快(在最好的情况下当然)。此外,如果我能够实现平衡的二叉搜索树,则可能是一种选择,但我遇到了麻烦,我将跳过它。
  • 当然你应该使用平衡树。你不应该跳过它,它是有用的知识/技能。随便google“avl tree”或者“red-black tree”,教程很多。​​
  • 我应该跳过它,因为我有截止日期,而且我现在没有时间学习新东西。我不会仅仅因为我想变得更有知识或更有技巧而让这门课不及格。我有时间,完成这个项目?没那么多……
  • 平衡树不如开放地址哈希表紧凑。
【解决方案3】:

我认为没有一种方法可以构建支持两个键的单个哈希表。

如果您希望 SSN-lookup 和 name-lookup 都非常快,那么您需要两个哈希表。您必须记住将它们都添加到它们中,或者从它们中删除。

否则,您可以将更频繁的一个(例如 SSN 查找)作为基于哈希的查找,而将另一个作为来自哈希表的暴力查找。

【讨论】:

  • 不...如果我使用蛮力查找,我的成绩可能会非常低。这个项目的重点是为每个案例使用“最好的”数据结构(我们在上学期学到的)。只要我们适当地证明它们的合理性,我们就可以使用任何东西。在我看来,哈希表是答案(当然是我的项目)。
  • @Nazgulled:感谢您澄清上下文。似乎最小化时间复杂性是您的目标。然而,根据具体情况,最小化空间复杂性也是一个崇高的目标! :-) 确定你的目标是什么。
【解决方案4】:
  1. 如你所说的两个哈希表。优点是查找 RANDOM 数据甚至真实数据的速度非常快。缺点是你不知道你的教授会怎么做(或者你知道吗?),他们可能会迫使最坏的情况发生。

  2. 平衡搜索树。我推荐 treaps:http://en.wikipedia.org/wiki/Treap - 在我看来,它们是最容易实现的。

  3. 对用户进行排序和二分搜索。每次搜索也是 O(log N),甚至比 treap 更容易实现。

  4. 哈希+排序用户/搜索树的组合,如果你能负担得起内存的话。这将使其成为 O(1) 最佳情况和 O(log N) 最坏情况。如果 H[i] = 散列到 i 的对象列表,请为每个 i 保留一个计数,告诉您该列表中有多少对象。如果该计数太大,请改用已排序的用户列表/搜索树。

【讨论】:

  • 他们正在为我们测试我们的程序准备一个数据样本,是的,但我们还没有访问它的权限。但是他们怎么能强迫最好/最坏的情况呢?这不取决于哈希函数吗?
  • 它确实取决于散列函数,但如果他们有权访问您的散列函数,他们可能会提出将触发其最坏情况行为的测试数据。我不认为他们会真正做到这些,但这是可能的。在哈希表中找到映射到同一位置的两个不同名称就足够了,然后给您一个包含 100 000 个用户的列表,所有用户都具有这两个不同的名称。然后搜索会很慢。为了获得最佳运行时间,您最好的选择是我列表中的#4。唯一的缺点是使用的内存,但它确实避免了最坏的情况。
  • 我不认为他们会打扰那么远,哈哈……谢谢你的提示:)
  • 好吧,如果你得到 O(log N) 最坏的情况,你肯定会给你的教授留下深刻印象:)。实际上,您可以先构建哈希表,如果您的哈希表不够平衡,则只保留一个树/排序列表。这样,您只会在最坏的情况下使用更多内存。
  • 我们会看到,一次一件事...... :)
【解决方案5】:

将两个键连接起来用作键呢?

例如我有 x、y、z。

使用字符串或字符作为分隔符连接 x 和 y。这是一种简单的方法。

在这篇文章中,我看到了这个解决方案可能更有趣的地方: Multi-dimensional associative arrays in javascript

【讨论】:

    猜你喜欢
    • 2018-11-05
    • 1970-01-01
    • 2021-02-13
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    相关资源
    最近更新 更多