Algorithm 备选秩函数RBTree(红黑树)

Algorithm 备选秩函数RBTree(红黑树),algorithm,rank,red-black-tree,Algorithm,Rank,Red Black Tree,我有一个顺序统计扩充红黑树 它在很大程度上起作用。但是我需要实现一个快速函数olgn,它主要以排序顺序返回节点的位置。就像我课本上的OS秩函数。但有一个转折点:如果两个节点具有相同的分数,则返回值应该相同。下面是伪代码中的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 但是:我需要的

我有一个顺序统计扩充红黑树

它在很大程度上起作用。但是我需要实现一个快速函数olgn,它主要以排序顺序返回节点的位置。就像我课本上的OS秩函数。但有一个转折点:如果两个节点具有相同的分数,则返回值应该相同。下面是伪代码中的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,而节点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.nodeswithkeyhigherkey函数中

编辑:答案的最后一段,感谢Sticky

tl;dr:跳到最后几段

这正是我遇到的问题。是的,我也是。到目前为止,除了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;
    }
让我们首先在第340页图14.1的树上测试这个方法。我们将搜索38的排名,该排名应返回4,因为39、47和41更高:

r=1+1=2//右侧+1 r=2//因为我们是对的孩子,所以什么都没有发生 r=r+1+1=4//我们是一个左撇子,父项的键更大,parent.Right.size=1 r=4//因为我们是对的孩子,所以什么也没发生 因此,在这种情况下,结果是正确的。但是,如果我们在树中添加另一个键为38的节点,会怎么样呢。这稍微改变了树的形状,节点26的右侧部分现在看起来像:

我还不允许添加图像,请看这里:http://i47.tinypic.com/358ynhh.png

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

r=0+1=1//无右侧 r=1//我们是对的孩子 r=1//我们是对的孩子 r=1+3+1=5//3来自节点41的大小。 r=5//我们是对的孩子 虽然我们期望排名第四。当我输入这个时,我注意到我们检查y.Score==y.Parent.Score,但我完全忘记了y的变化。因此在第4行中,子句y.Score==y.Parent.Score为false,因为我们比较了节点30和节点38。因此,如果我们将该行更改为:

if (x.Score == y.Parent.Score)
算法输出秩4,这是正确的。这意味着我们消除了另一个问题。但还有更多,我也没有弄清楚:

Y.Parent.Right包含重复键的情况。从技术上讲,如果有3个节点具有相同的密钥,则它们应计为1。 在这种情况下,Y.Parent.Right包含与x相等的键。为想要排名的节点设置键。这将使我们落后几级,这是错误的。 我想您可以保留另一个整数,该整数包含得分较高的节点数。插入后,如果该节点的子树不包含具有相同分数的节点,则可以爬树并调整值。但我现在还不知道这是如何有效地完成的。
编辑:首先找到得分相同的x的最终继任者。然后用常规方法计算秩。上面的代码有效。

哦……谢谢……这很有帮助……那么我最好开始使用sticky。。。听起来我好像错过了一些潜在的优势。不知怎的,我的车在截止日期前18分钟奇迹般地越过了栅栏,尽管它仍然有一些本应足以让它失败的故障。这意味着你和sticky救了我一命。我非常感激。