【问题标题】:What is the time complexity of TreeSet iteration?TreeSet 迭代的时间复杂度是多少?
【发布时间】:2010-05-03 15:45:30
【问题描述】:

在我的代码中,Java TreeSet 迭代是主要的时间因素。在查看系统时,我认为它是 O(n) 复杂度。任何人都可以验证这一点吗?

我认为通过提供从子节点到父节点的反向链接可以提高性能。

【问题讨论】:

  • 这个问题没有意义。听起来你在说迭代你的树集是 O(n)。这是您可以为迭代做的最好的事情 - 查看 n 个项目需要 O(n) 时间。如果您想让以迭代为主的代码更快,您需要更改算法,使其不进行迭代 - 例如,通过键在树中进行查找(这将是 O(log n))而是。

标签: java algorithm data-structures treeset


【解决方案1】:

TreeSet 迭代当然是 O(n),正如任何合理的树遍历算法都可以预期的那样。

我认为通过提供链接 从子节点向后退到父节点 节点我可以提高性能。

TreeMapTreeSet 的基础)已经有这样的父引用。这就是它归结为的方法:

private Entry<K,V> successor(Entry<K,V> t) {
    if (t == null)
        return null;
    else if (t.right != null) {
        Entry<K,V> p = t.right;
        while (p.left != null)
            p = p.left;
        return p;
    } else {
        Entry<K,V> p = t.parent;
        Entry<K,V> ch = t;
        while (p != null && ch == p.right) {
            ch = p;
            p = p.parent;
        }
        return p;
    }
}

【讨论】:

  • 我认为关键是不仅叶节点有附加值。对于n 叶子,您确实有O(n log n) 节点,但也有O(n log n) 值。在实际情况下,我希望O(n) 操作无论如何都会主导O(n log n) 操作。
  • 我认为这将是 O(n)+O(logn) 因为如果您要按顺序进行迭代,则必须首先使用 log(n) 遍历来找到左侧或最右侧的叶子,然后您有 n 次遍历来向后走树。因此你有 O(n) ?我的数学有意义吗?
  • @john: O(n)+O(log n) 与 O(n) 的定义相同。
  • @Tom:O(nlog n) 严格大于 O(n),但是对于 n 个叶子来说,你有 O(nlog n) 个节点是不正确的.对于具有 n 个叶子的二叉树,在倒数第二级有 n/2 个节点,在下一个更高级别有 n/4 个节点……这是一个几何级数,加起来为 2n,即 O(n)。
  • 第二部分是正确的(但这显然是一个错误!)。虽然 O(n log n) 比 O(n) 更复杂,但对于 n 的实际值,在后者中执行 O(n log n) 和 O(n) 可能需要更长的时间。
【解决方案2】:

您是否考虑过在更改 TreeSet 时复制它?如果支配时间花费在 TreeSet 迭代中(而不是修改它),那么将 TreeSet 复制到数组或 ArrayList(仅在更改时)并且仅在此数组/ArrayList 上进行迭代几乎可以消除 TreeSet 迭代的成本。

【讨论】:

  • 或者 Guava 的 ImmutableSortedSet,它是数组支持的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
  • 2014-01-14
  • 1970-01-01
相关资源
最近更新 更多