首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按序号索引访问红黑树

按序号索引访问红黑树
EN

Stack Overflow用户
提问于 2012-03-31 14:20:25
回答 3查看 1.8K关注 0票数 2

我有一棵红黑相间的树(二叉树,所有的叶子都在两层之内)。我可以通过节点导航:向左、向右或向父节点。我知道所有的节点数。

我必须找到树中的第N个最小的元素。有没有比O(n)更快的方法呢?有没有通过索引优化访问的想法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-31 14:49:15

在你应该存储的每个节点X中,有多少个节点在以X为根的子树中。

代码语言:javascript
复制
count(LEAF) = 1
count(NODE) = count(NODE->LEFT) + count(NODE->RIGHT) + 1

在每次插入/删除期间,您应该使用此公式来更新受旋转影响的节点中的计数。

之后,解决方案就很简单了

代码语言:javascript
复制
NODE nth(NODE root, int n) {
    if (root->left->count <= n) return nth(root->left, n);
    if ( root->left->count + 1 == n) return root;
    return nth(root->right, n - root->left->count - 1);
}
票数 3
EN

Stack Overflow用户

发布于 2012-03-31 14:47:37

您可以在每个节点中添加一个属性,以显示此节点的子节点数量。有了这个属性,你可以找到第N个最小的节点,O(lgn)。

现在,当您在树中插入(或删除)任何节点时,您只需处理此属性。如果没有旋转,那么它很容易处理,但是当你有旋转的时候,它就有点困难了,但你可以做到。

票数 3
EN

Stack Overflow用户

发布于 2017-05-25 13:23:47

对于红黑树,你不需要跟踪左边的节点数,因为如果它是右偏的(应该是),那么左边的节点数将总是形成一个mersenne序列( 1,3,7,15,31 ...)或者2^depth -1

考虑到这一点,我们可以写下递归获取节点的逻辑。上面接受的答案有它的符号切换。这是elixir中的正确实现。对于package

代码语言:javascript
复制
def nth(%Rbtree{node: r}, n), do: do_nth(r, n)
defp do_nth({_,h,k,v,l,r}, n) do
  l_count = left_count(h)
  cond do
    l_count > n ->
      case l do
        nil -> {k,v}
        _ -> do_nth(l, n)
      end
    l_count == n -> {k,v}
    true ->
      case r do
        nil -> {k,v}
        _ -> do_nth(r, n - l_count - 1)
      end
  end
end
defp left_count(1), do: 0
defp left_count(0), do: 0
defp left_count(h), do: :math.pow(2,h-1)-1 |> round
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9953557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档