【问题标题】:A good data structure for storing and searching integers?用于存储和搜索整数的良好数据结构?
【发布时间】:2017-10-09 01:50:09
【问题描述】:

编辑:错别字已修复,歧义已尝试修复。

我在一个文本文件中有一个五位整数的列表。预期数量只能与 5 位整数可以存储的一样大。不管有多少,这个文件中的第一行告诉我有多少个整数,所以永远不需要调整大小。示例:

3
11111
22222
33333

有 4 行。第一个表示文件中有三个 5 位整数。接下来的三行包含这些整数。

我想读取这个文件并存储整数(不是第一行)。然后我希望能够大量搜索这个数据结构,仅此而已。我要做的就是读取数据,将其放入结构中,然后能够确定其中是否有特定的整数。永远不会发生删除。在这个结构上做的唯一事情就是插入和搜索。

您认为合适的数据结构是什么?我最初的想法是某种二叉树。但是,经过思考,HashTable 可能是最好的实现。请给点意见和帮助?

【问题讨论】:

  • The expected amount could be in the millions ... 但最大的五位数字是 100,000 的 1。您的搜索的性质是什么?
  • Deletions will never occur. The only things done on this structure will be insertions and deletions. ... 错字?
  • 如果有数百万个整数都低于 99999,那么我可能会使用一桶数字计数。 numbers = new int[100000]; 然后通过索引它的桶来获取一个数字的出现。
  • 您能详细说明您正在执行的操作吗?是纯粹的插入和删除吗?您是否需要能够按排序顺序进行迭代?在某个范围内搜索?合并东西?是否允许重复?
  • “经过思考,HashTable 可能是最好的实现” -> HashSet.

标签: java data-structures


【解决方案1】:

看来你的要求是

  • 存储一堆整数,
  • 插入速度很快,
  • 查找速度很快,并且
  • 绝对没有其他问题。

如果您正在处理“足够小”的整数范围 - 例如,大约 16,000,000 左右的整数,您可以为此使用位向量。您会为每个数字存储一位,最初都是零,然后在输入数字时将这些位设置为活动状态。这具有极快的查找和极快的设置,但如果整数可以是完全任意的,则非常占用内存且不可行。这可能由BitSet 建模。

如果您正在处理任意整数,哈希表可能是这里的最佳选择。使用良好的散列函数,您将获得跨表槽的良好分布和非常非常快速的查找。为此,您需要HashSet

如果您绝对必须不惜一切代价保证最坏情况下的性能并且您正在处理任意整数,请使用平衡 BST。 BST 中的间接成本使它们比其他数据结构慢一点,但平衡的 BST 可以保证哈希表无法保证的最坏情况下的效率。这将由TreeSet 表示。

【讨论】:

  • 这很有帮助!非常感谢。我必须从头开始实现数据结构,不允许使用 Java.util 或任何其他 Java 实现。我打算使用哈希表,但我更喜欢 BST,因为我更了解它们。我认为解释我可以保证最坏情况下的效率也是一个好主意!非常感谢。
  • 仅供参考,第一个概念由java.util.BitSet实现。
  • @shmosel 我不知道它的存在!感谢分享!
【解决方案2】:

鉴于此

  • 所有数字都是
  • 您只想检查数字是否存在

您可以简单地使用某种形式的位图。

例如创建一个byte[12500](它是 100,000 位,这意味着 100,000 个布尔值来存储 0-99,999 的存在)

“插入”一个数字 N 意味着打开第 N 位。搜索数字 N 意味着检查第 N 位是否打开。

插入逻辑的伪代码为:

bitmap[number / 8] |= (1>> (number %8) );

搜索看起来像:

bitmap[number/8] & (1 >> (number %8) );

如果您了解其中的原理,那么对您来说是一个更好的消息:在 Java 中,我们已经有了 BitSet,它正在执行我上面描述的操作。

所以代码如下所示:

BitSet bitset = new BitSet(12500);

// inserting number
bitset.set(number);

// search if number exists
bitset.get(number);  // true if exists

【讨论】:

    【解决方案3】:

    如果每个数字出现的次数无关紧要(如您所说,只插入并查看该数字是否存在),那么您最多只能有 100,000 个。只需创建一个布尔数组:

    boolean numbers = new boolean[100000];
    

    这应该只占用 100 KB 的内存。

    然后,不要添加数字,例如 11111、22222、33333:

    numbers[11111]=true;
    numbers[22222]=true;
    numbers[33333]=true;
    

    要查看一个数字是否存在,只需执行以下操作:

    int whichNumber = 11111;
    numberExists = numbers[whichNumber];
    

    你来了。易于阅读,易于维护。

    【讨论】:

      【解决方案4】:

      Set 是“查找”的首选数据结构,您需要编写少量代码:

      Scanner scanner = new Scanner(new FileInputStream("myfile.txt"));
      Set<Integer> numbers = Stream.generate(scanner::nextInt)
          .limit(scanner.nextInt())
          .collect(Collectors.toSet());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-24
        • 2011-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多