我有一个订单统计增强红黑树。
它在很大程度上起作用。但我需要实现一个快速函数(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)函数中)。
答案 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更高):
所以在这种情况下结果是正确的。但是如果我们将另一个带有键38的节点添加到树中呢。这稍微重塑了我们的树,节点26的右边部分现在看起来像:
(我不允许添加图片,所以请看这里:http://i47.tinypic.com/358ynhh.png)
如果我们使用相同的算法,我们会得到以下结果(选择红色):
虽然我们期待这里排名第4。当我输入这个时,我注意到我们检查是否y.Score == y.Parent.Score,但我完全忘记了y更改。所以在第4行中,“y.Score == y.Parent.Score”这个子句是假的,因为我们将节点30与38进行了比较。所以如果我们将该行改为:
if (x.Score == y.Parent.Score)
算法输出等级4,这是正确的。这意味着我们消除了另一个问题但还有更多,我也没想到:
编辑:首先找到具有相同分数x的x的最终后继者。然后以正常方式计算排名。上面的代码可以工作。