【问题标题】:How to find the rank of a node in an AVL tree?如何找到 AVL 树中节点的等级?
【发布时间】:2015-10-04 00:52:21
【问题描述】:

我需要实现两个排名查询 [rank(k)select(r)]。但在开始之前,我需要弄清楚这两个函数是如何工作的。

据我所知,rank(k) 返回给定键的等级kselect(r) 返回给定等级的键r

所以我的问题是:

1.) 如何计算 AVL(自平衡 BST)中节点的排名?

2.) 多个键是否有可能具有相同的等级?如果是这样,select(r) 会返回什么?

我将包含一个示例 AVL 树,如果它有助于回答问题,您可以参考它。

谢谢!

【问题讨论】:

  • +1: 包含一个供参考的数字:-)

标签: algorithm binary-tree binary-search-tree


【解决方案1】:

您的问题实际上可以归结为:“对于 AVL 树,‘等级’一词通常是如何定义的?” (可能还有“选择”通常是如何定义的)。

至少正如我所看到的那样,“排名”是指树中节点之间的位置——即它左边有多少个节点。您通常会得到一个指向节点(或者可能是键值)的指针,您需要计算其左侧的节点数。

“选择”基本上是相反的——你被赋予了一个特定的等级,并且需要检索一个指向指定节点的指针(或该节点的键)。

两个注意事项:首先,由于这些都不会修改树,因此使用哪种形式的平衡并没有真正的区别(例如,AVL 与红/黑);就此而言,一棵完全没有平衡的树也是等价的。其次,如果您需要经常这样做,您可以通过向每个节点添加一个额外的字段来记录其左侧有多少个节点,从而大大提高速度。

【讨论】:

  • 是的,这是正确的。当您说“计算其左侧的节点数”时,您是指左子树吗?例如,rank(10) 是否为 0?另外,有人告诉我,我可以使用大小参数来优化代码,这可能与您所说的提高速度有关。有没有可以推荐的链接,我可以在哪里找到如何实施这个?再次感谢。
  • IIRC,它通常是整个树中左侧的所有节点,因此 rank(10) 将是 5 或 6(取决于您是从 0 开始还是从 1 开始)。顺便说一句,我不知道关于这个主题的任何好的链接,但是 Cormen、Leiserson、Rivest 和 Stein 的 IIRC 算法简介有一个部分。
  • 嗯,好的。所以我很清楚这一点;你会说 rank(13) 会是 7 还是 8?
  • 我猜作业的主要问题是如何平衡树以便能够保持计数。对于局部旋转,这始终是可能的(因此甚至适用于红黑树等)。我相信这个结构的名称是订单统计树。 +1,不过。
  • @Jerry Coffin:我明白了。好的,据我所知,每个节点都有一个唯一的排名。因此,当我们运行select(r) 时,它将始终返回具有该特定等级的一个节点。这是真的? @Moron:谢谢,我会调查一下,看看它是否有助于解决我的问题。
【解决方案2】:

Rank 是左子树中的节点数加一,是针对每个节点计算的。我相信等级不是 AVL 树特有的概念——它可以为任何二叉树计算。

选择与排名正好相反。给出了一个排名,您必须返回一个与该排名匹配的节点。

以下代码将执行排名计算:

void InitRank(struct TreeNode *Node)
{
        if(!Node)
        {
                return;
        }
        else
        {       Node->rank = 1 + NumeberofNodeInTree(Node->LChild);
                InitRank(Node->LChild);
                InitRank(Node->RChild);
        }

}


int NumeberofNodeInTree(struct TreeNode *Node)
{
        if(!Node)
        {
                return 0;
        }
        else
        {
                  return(1+NumeberofNodeInTree(Node->LChild)+NumeberofNodeInTree(Node->RChild));
        }
}

【讨论】:

    【解决方案3】:

    这是我为 AVL 树编写并运行良好的代码,以获取特定值的排名。区别只是你使用了一个节点作为参数,而我使用了一个键作为参数。您可以按照自己的方式进行修改。示例代码:

        public int rank(int data){
        return rank(data,root);
    }
    
    private int rank(int data, AVLNode r){
        int rank=1;
        while(r != null){
            if(data<r.data)
                r = r.left;
            else if(data > r.data){
                rank += 1+ countNodes(r.left);
                r = r.right;
            }
            else{
                r.rank=rank+countNodes(r.left);
                return r.rank;
            }
        }
        return 0;
    }
    

    [N.B] 如果您想从 0 开始排名,则初始化变量 rank=0。 你绝对应该实现 countNodes() 方法来执行这段代码。

    【讨论】:

      猜你喜欢
      • 2021-02-18
      • 1970-01-01
      • 2015-05-03
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多