【问题标题】:Hash Tables or BST?哈希表还是 BST?
【发布时间】:2016-12-14 05:30:30
【问题描述】:

目前我有一个问题正在尝试解决,但不确定我的答案是否正确。

您有 100 万条记录。在这些记录中,您经常需要搜索 两个标准:员工 ID 和薪水(但不能同时通过两者)。 您有以下限制:

  • 每条记录都非常大,因此您只能保留一份此数据的副本。

  • 您的程序需要相当快。每次搜索时简单地扫描所有项目太慢了。

你会使用什么数据结构?

我的答案?

我会使用哈希表,因为最坏情况的时间是 O(1000000) = O(1)

当您通过 ID 搜索时,您将如何检索记录?

按工资搜索时如何检索记录?

【问题讨论】:

  • 您是否需要按薪资范围进行搜索? (例如“告诉我所有工资在 20,000 美元到 25,000 美元之间”或类似的?)如果是这样,您需要扫描整个哈希表 (O(N)) 才能做到这一点,因为哈希表的 O(1) 查找仅如果您知道要查找的确切键值,则可以工作...
  • “使用哈希表”只是答案的开始。您将如何仅使用一份数据副本搜索两个键?我认为这就是问题试图探讨您的知识的问题。树和哈希表之间的选择是次要的,您可以同时使用两者。想想缺少的细节。您是否必须通过一系列薪水进行搜索 - 这是现实的 - 或特定的美元价值 - 不是那么有用?区别很重要。
  • @JeremyFriesner 很好的 ID 我会知道确切的位置是我先对 ID 进行排序然后使用哈希?但是对于薪水你有一点......
  • @Gene 我认为在这种情况下它实际上是一个特定的美元价值。我说散列是因为如果我有一百万条记录,那么对它们进行排序和散列会更容易,因此 ID 需要 O(1) 时间,但对于工资,我被卡住了,因为我只有一个副本。
  • @BassamMetwally 如果我理解正确,您似乎不太可能使用哈希表作为工资,因为假设多个员工可能具有相同的值是现实的,这会在尝试时导致冲突散列键(除非有一些保证工资也是唯一的?)另外,您是否允许引用记录,或者必须将实际记录对象存储在数据结构中?

标签: c hashtable binary-search-tree


【解决方案1】:

我预计基于薪水的哈希表会出现许多冲突问题,但使用一点密码学理论,ID 可以很容易地在没有冲突的情况下工作。想要按薪水搜索而不是排序或获取某个范围似乎很奇怪,这在 BST 上执行起来要容易得多。

但它的缺点是,如果您想通过两个独立的属性进行搜索,您将不得不维护两个结构。幸运的是存在指针,因此您不必保留多个副本。就我个人而言,我会保留一个 ID 哈希表到引用,然后是工资的 BST 到引用,但如果我仅限于一种数据类型,我必须使用这样的节点进行 BST:

    Node {
        int id;
        Node idLessThan;
        Node idGreaterThan;

        int salary;
        Node salaryLessThan;
        Node salaryGreaterThan;

        Data fileInfo;
    }

在同一个节点集上创建两个 BST。

【讨论】:

  • 我在评论时也有同样的想法。但是,如果薪水是独一无二的呢?哈希表会更好吗?
  • 如果您只想按薪水搜索而不是按薪水排序,则在内存和访问时间上都会更有效。我能想到的任何你只想按确切工资搜索的情况都是很做作的。
  • 因此,如果我只搜索,使用 BST 会很有效。我理解,但这是一个测试我们对概念理解的问题。
  • 精确搜索比哈希表更有效,但在 BST 中查找所有大于 x 的薪水就像查找 x 并返回 salaryGreaterThan 节点的所有子节点一样简单(事实有点复杂x 可能不在表中,但仍然比为哈希表检查 $20,000 到 $25000 之间的每个值的哈希值要高效得多)
  • 如果你想在你的哈希表中使用薪水作为键,并且还支持几个人有相同薪水的情况,你可以通过将哈希表的值设置为 type list-of-people 而不是类型 person。然后,当将一个人添加到表中时,您会检查他的薪水是否已经作为键存在;如果是,则将该人添加到与该薪水相关的列表的末尾;如果没有,请使用该键插入一个新列表,并且只插入列表中的一个人。
猜你喜欢
  • 2018-01-06
  • 1970-01-01
  • 1970-01-01
  • 2013-09-26
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 2011-01-22
  • 2016-10-04
相关资源
最近更新 更多