替代等级函数RBTree(红黑树)

时间:2012-06-28 02:38:30

标签: algorithm rank red-black-tree

我有一个订单统计增强红黑树。

它在很大程度上起作用。但我需要实现一个快速函数(O(lg n)),它主要以排序顺序返回节点的位置。喜欢我教科书中的OS-rank功能。但有一个转折:如果两个节点具有相同的分数,则返回值应该相同。这是os-rank函数(在伪代码中,对于给定节点x,其中root是树的根)。

OS-Rank(x)
r=x.left.size+1
y=x
while y!=root
  if y==y.p.right
    r+=y.p.left.size+1
y=y.p
return r

但是:我需要的是,如果A有密钥1而Node B有密钥1,则该函数返回1。等等。我尝试过这样的事情。

rank(x)
start with value r=1
check that x.right is not Nil
  case x.right has the same key as x
    add x.right.#nodeswithkeyhigher(x.key) to r
  other cases: add x.right.size to r
y=x
while y != root
  if y.parent.left == y
    case y.parent.right.key>x.key
      add y.parent.right to r
    other cases
      add y.parent.right.#nodeswithkeyhigher(x.key) to r
  y=y.parent
return r

猜猜是什么:测试用例失败了。我想知道这是否是一种正确的做事方式,或者如果我犯了一些我没有看到的错误(否则错误就在Node。#nodeswithkeyhigher(key)函数中)。

1 个答案:

答案 0 :(得分:0)

编辑:最后一段回答,感谢Sticky。

tl; dr:跳到最后一段

这是我遇到麻烦的同一个问题。 (是DS以及)。到目前为止,除了5个以外的所我测试了几个东西,一个是非常简单的:只需在OSRank中左右交换。在某些情况下,它给出了正确的答案,但在更难的情况下它是相当有点的。哦,我还补充说如果y.score == y.parent.score我只添加正确大小的y.parent,如果不是我添加正确的大小+ 1.

public int OSRank(Node x)
    {
        int r = x.Right.Size + 1;
        Node y = x;
        while (y != root)
        {
            if (y == y.Parent.Left)
            {
                if (y.Score == y.Parent.Score)
                    r = r + y.Parent.Right.Size;
                else
                    r = r + y.Parent.Right.Size + 1;
            }
            y = y.Parent;
        }
        return r;
    }

让我们首先在树上测试这种方法(第34页)。我们将搜索等级38(应该返回4,因为39,47和41更高):

  1. r = 1 + 1 = 2 //右侧+ 1
  2. r = 2 //没有任何反应,因为我们是一个正确的孩子
  3. r = r + 1 + 1 = 4 //我们是一个左孩子,我们父母的钥匙更大而且parent.Right.size = 1
  4. r = 4 //因为我们是一个正确的孩子而没有任何反应
  5. 所以在这种情况下结果是正确的。但是如果我们将另一个带有键38的节点添加到树中呢。这稍微重塑了我们的树,节点26的右边部分现在看起来像:

    (我不允许添加图片,所以请看这里:http://i47.tinypic.com/358ynhh.png)

    如果我们使用相同的算法,我们会得到以下结果(选择红色):

    1. r = 0 + 1 = 1 //没有右侧
    2. r = 1 //我们是一个正确的孩子
    3. r = 1 //我们是一个正确的孩子
    4. r = 1 + 3 + 1 = 5 // 3来自节点41的大小。
    5. r = 5 //我们是一个正确的孩子
    6. 虽然我们期待这里排名第4。当我输入这个时,我注意到我们检查是否y.Score == y.Parent.Score,但我完全忘记了y更改。所以在第4行中,“y.Score == y.Parent.Score”这个子句是假的,因为我们将节点30与38进行了比较。所以如果我们将该行改为:

      if (x.Score == y.Parent.Score)
      

      算法输出等级4,这是正确的。这意味着我们消除了另一个问题但还有更多,我也没想到:

      • Y.Parent.Right包含重复键的情况。从技术上讲,如果我们有3个具有相同密钥的节点,则它们应该计为1。
      • Y.Parent.Right包含等于x.Key(您想要排名的节点)的键的情况。这会给我们带来一些不正确的排名。

      我想你可以保留另一个整数,它保存得分较高的节点数量。插入后,如果该节点的子树不包含具有相同分数的节点,则可以爬树并调整值。但是我现在还不知道如何(并且有效地)完成这项工作。

      编辑:首先找到具有相同分数x的x的最终后继者。然后以正常方式计算排名。上面的代码可以工作。