【问题标题】:What is the time complexity of ordered operations in TreeSet?TreeSet 中有序操作的时间复杂度是多少?
【发布时间】:2011-03-07 00:53:11
【问题描述】:

java.util.TreeSet中以下操作的时间复杂度是多少?

  • first()
  • last()
  • lower()
  • higher()

我会假设这些是恒定时间,但 API 不做任何保证。

【问题讨论】:

    标签: java algorithm complexity-theory treeset


    【解决方案1】:

    实际上,我原以为这些操作都将是O(logN) 用于一般实现。

    • 为了使first()last() 成为O(1),TreeSet 实现需要分别维护一个指向树中最左边和最右边叶子节点的指针。维护这些会增加每次插入的恒定成本,并且至少会增加每次删除的恒定成本。实际上,该实现可能会即时找到最左边/最右边的节点......这是一个O(logN) 操作。

    • lower()higher() 方法必须与 get 完成相同的工作,因此是 O(logN)

    当然,您可以自己检查源代码以了解实际发生的情况。 (正如其他人所做的那样:见下文。)

    【讨论】:

    • 我看了看源代码,但它太抽象了。我不确定第一个和最后一个在哪里实施。得再看看。
    • TreeSet 在内部使用 TreeMap 实现,因此大部分逻辑都在 TreeMap.get[First|Last|Lower|Higher]Entry() 中。全部遍历树以找到节点,因此 Stephen C 是正确的,O(log N)。
    【解决方案2】:

    根据 TreeSet 默认使用的 TreeMap 的 Implentation(sun jdk 1.6.0_23),first() 和 last() 看起来都是 O(log n) 而不是 O(1):

     /**
     * Returns the first Entry in the TreeMap (according to the TreeMap's
     * key-sort function).  Returns null if the TreeMap is empty.
     */
    final Entry<K,V> getFirstEntry() {
        Entry<K,V> p = root;
        if (p != null)
            while (p.left != null)
                p = p.left;
        return p;
    }
    
    /**
     * Returns the last Entry in the TreeMap (according to the TreeMap's
     * key-sort function).  Returns null if the TreeMap is empty.
     */
    final Entry<K,V> getLastEntry() {
        Entry<K,V> p = root;
        if (p != null)
            while (p.right != null)
                p = p.right;
        return p;
    }
    

    【讨论】:

      【解决方案3】:

      其实我查了源代码, 在http://developer.classpath.org/doc/java/util/TreeSet-source.html 中,first() 调用 maps.firstKey() 然后在 http://developer.classpath.org/doc/java/util/TreeMap-source.html

      393: public K firstKey()
      394: (
      395: if (root == nil)
      396: throw new NoSuchElementException();
      397: return firstNode().key;
      398: )
      

      在 firstNode() 中,它执行 while 循环一直到左侧

      952: final Node<K, V> firstNode()
      953: (
      954: // Exploit fact that nil.left == nil.
      955: Node node = root;
      956: while (node.left != nil)
      957: node = node.left;
      958: return node;
      959: )
      

      【讨论】:

        【解决方案4】:

        这将取决于实施。我对 JAVA 不是很熟悉,但似乎所有这些操作都是遍历操作(获取最低元素,获取最高元素,获取下一个更高或下一个更低的元素)。

        如果 Tree 实现为 Self-Balancing Binary Search Tree(如 AVL Tree)或任何其他类型的平衡树结构,您将看到平均情况和最坏情况 O(log n)每个操作的时间,以及 O(1) 的最佳情况。

        【讨论】:

        • 但是实现被指定为红黑树,所以不依赖于实现。
        【解决方案5】:

        API 不做任何保证,因为这些都是基于 trie 的标准模型。最好的情况是 O(1),平均情况是 O(log n),最坏的情况是 O(n)。

        来自文档:

        此实现为基本操作(添加、删除和包含)提供有保证的 log(n) 时间成本。

        这些不是您要求的函数,但请考虑一下 Java 将如何遍历 TreeSet。

        【讨论】:

        • 哈哈,现在修好了 ;)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-01
        • 1970-01-01
        • 2019-07-15
        • 2011-03-24
        • 2015-03-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多