【问题标题】:AVL Trees: How to do index access?AVL 树:如何进行索引访问?
【发布时间】:2012-06-12 22:24:25
【问题描述】:

我在AVL Tree Wikipedia page 上注意到以下评论:

“如果每个节点都额外记录了它的子树的大小(包括它自己和它的后代),那么这些节点也可以在O(log n)时间内通过索引来检索。”

我已经用谷歌搜索并找到了一些提到accessing by index 的地方,但似乎无法找到一个人会写的算法的解释。

非常感谢

[更新] 谢谢大家。如果发现 @templatetypedef 答案与 @user448810 links 之一结合起来特别有帮助。尤其是这个片段:

"这两个函数的关键是一个节点的索引是它的左孩子的大小。只要我们通过它的左孩子降序一棵树,我们只取节点的索引。但是当我们必须通过它的右子树向下移动,我们必须调整大小以包括我们排除的树的一半。”

因为我的实现是不可变的,所以在重新平衡时我不需要做任何额外的工作,因为每个节点都会在构造时计算它的大小(与 impl 链接的方案相同)

我的最终实现是:

class Node<K,V> implements AVLTree<K,V> { ...
    public V index(int i) {
        if (left.size() == i) return value;
        if (i < left.size()) return left.index(i);
        return right.index(i - left.size() - 1);
    }
}

class Empty<K,V> implements AVLTree<K,V> { ...
    public V index(int i) { throw new IndexOutOfBoundsException();}
}

这与其他实现略有不同,如果您认为我有错误,请告诉我!

【问题讨论】:

    标签: algorithm data-structures tree indexing avl-tree


    【解决方案1】:

    这种构造背后的总体思路是采用现有的 BST 并通过存储左子树中的节点数来扩充每个节点。完成此操作后,您可以使用以下递归算法查找树中的第 n 个节点:

    • 要查找 BST 中的第 n 个元素,其根节点的左子树中有 k 个元素:
      • 如果 k = n,则返回根节点(因为这是树中的第 0 个节点)
      • 如果 n ≤ k,递归查找左子树中的第 n 个元素。
      • 否则,在右子树中查找第 (n - k - 1) 个元素。

    这需要时间 O(h),其中 h 是树的高度。在 AVL 树中,这个 O(log n)。在 CLRS 中,这种构造被探索为应用于红/黑树,他们称这种树为“顺序统计树”。

    你必须在树的旋转过程中加入一些额外的逻辑来调整左子树中缓存的元素数量,但这并不是特别困难。

    希望这会有所帮助!

    【讨论】:

    • 虽然我同意这是做事的正确方式,但它似乎与 Wiki 页面所覆盖的不太一样(它存储整个子树的大小,而不是左子树)。他们正在做的事情(显然)需要一点笨拙,通过减去右子树的大小或查看左子树的大小来推导左子树的大小。
    • @JerryCoffin- 我勾勒出的方法与这种方法有关。如果每个子树都存储它的总大小,我可以通过查看左子树的总大小来查找左子树的大小(如果有的话)。这两种方法本质上是同构的。
    • 再想一想,我看到了他们系统的一个优势:它支持从任一端索引,因此从集合末尾索引 N 就像从一开始就索引 N 一样简单。
    • 这个答案是正确的。在 here 中查看 Scheme 中的示例实现,并在 here/here 中查看两部分解释,包括 nth(查找第 n 个键)和 rank(确定给定键的排名)函数。
    猜你喜欢
    • 2016-02-03
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    相关资源
    最近更新 更多