【问题标题】:How to retrieve elements from sorted TreeSet using Binary Search?如何使用二分搜索从排序的 TreeSet 中检索元素?
【发布时间】:2014-03-31 11:08:51
【问题描述】:

我正在尝试将多个排序列表合并到一个 TreeSet 中。然后我正在考虑在该 TreeSet 上应用二分搜索算法来检索 O(log n) 时间复杂度的元素。

下面是我的代码,其中我在其中一种方法中传递列表列表并将它们组合到TreeSet 以避免重复...inputs 中的所有列表都已排序 -

private TreeSet<Integer> tree = new TreeSet<Integer>();

public void mergeMultipleLists(final List<List<Integer>> inputs) {
    tree = new TreeSet<Integer>();
    for (List<Integer> input : inputs) {
        for(Integer ii : input) {
            tree.add(ii);
        }
    }
}

public List<Integer> getItem(final Integer x) {
    // extract elements from TreeSet in O(log n)
}
  • 首先,这是将多个排序列表合并到 TreeSet 中的正确方法吗?有没有直接的方法可以有效地合并 TreeSet 中的多个排序列表?
  • 其次,如何以 O(log n) 的时间复杂度从 TreeSet 中提取元素?我想在那个TreeSet中找到一个元素x,如果存在则返回它,如果不存在则从TreeSet返回下一个最大值。

或者与我目前使用的数据结构相比,我是否更适合使用另一种数据结构?

更新代码:-

私有 TreeSet 树 = new TreeSet();

public SearchItem(final List<List<Integer>> inputs) {
    tree = new TreeSet<Integer>();
    for (List<Integer> input : inputs) {
        tree.addAll(input);
    }
}

public Integer getItem(final Integer x) {
    if(tree.contains(x)) {
        return x;
    } else {
        // now how do I extract next largest 
         // element from it if x is not present
    }
}

【问题讨论】:

  • 您可以使用TreeSet.addAll() 而不是单独添加每个元素。它会节省一些 LOC,但我不知道它是否更有性能。
  • @MikeB:感谢addAll 的提示。我完全忘记了。现在关于我的第二个问题。有什么想法吗?
  • 看起来这里的讨论是相关的:stackoverflow.com/questions/3390449/…
  • “提取元素”是什么意思?你想得到xth 最大的元素吗?您要测试x 是否在TreeSet 中吗?你想得到等于x的元素吗(在这种情况下......你只需要返回x?)
  • 我想在那个TreeSet中找到一个元素x,如果存在则返回它,如果不存在则返回TreeSet中的下一个最大值。

标签: java list set treeset


【解决方案1】:

你可以使用 TreeSet.floor(),根据the docs

返回此集合中小于或等于给定元素的最大元素,如果没有这样的元素,则返回 null。

【讨论】:

    【解决方案2】:

    TreeSetNavigableMap 支持,特别是TreeMap。在TreeSet 上调用contains() 代表TreeMap.containsKey(),这是一种二分搜索实现。

    您可以使用TreeSet.contains() 来检查集合中是否包含对象,但您必须首先拥有该对象。如果您希望能够查找和检索对象,那么Map 实现会更好。

    【讨论】:

    • 谢谢 Mike.. 我用最新的代码更新了这个问题.. 早些时候我误解了,但在你的建议之后,几乎没有什么事情得到解决.. 但我在 else 声明中有一个疑问.. 采取看看我的代码..
    • 可能是TreeSet 中的higher() 方法?我从未使用过它,但它看起来像你想要的。为了将来参考,您可以先查看 javadocs,看看您的答案是否存在:docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html
    • 你确定它使用二进制搜索 imp?看看 TreeMap 中的Entry&lt;K,V&gt; getEntry,对我来说它看起来像是一个基于位置的“链接”搜索。
    • 自从我发布我的答案后,它可能已经改变了。不过,这在当时绝对是一种二分搜索实现。
    【解决方案3】:

    TreeSet,本质上是一个排序集,并通过 TreeMap 使用 red-tree-black-tree 作为它的支持

    基本上:TreeSet.add(E) -> TreeMap.put(E,NULL);

    由于它已经是二叉树结构,因此任何“get”或“contains”都将导致 O(log n) 操作。

    您的代码和您的问题虽然没有对齐。

    您将List&lt;List&lt;Integer&gt;&gt; 扁平化,然后将它们全部放入以获得所有唯一元素(或者,至少,这就是这段代码要做的)。

    但是你的下面的方法说“给定这个整数,给我一个List&lt;Integer&gt;”,这在上面的代码中是无法实现的

    那么,让我按顺序回答你的问题:

    1. 确定/是的
    2. 没有。你误解了 Sets(你不能按设计提取)如果你可以做 Set.contains(e) 那么你有元素并且不需要提取任何东西

    如果您需要执行“集合提取”之类的操作,请使用 TreeMap 或将您的集合转回列表并执行 myList.get(Collections.binarySearch(myElement));

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-06
      • 2020-02-24
      • 2020-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      相关资源
      最近更新 更多