如何在AVL树中找到节点的等级?

时间:2011-02-28 02:40:59

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

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

据我所知,rank(k)会返回给定键k的排名,select(r)会返回给定排名r的键。

所以我的问题是:

1.。)如何计算AVL中的节点等级(自平衡BST)?

2。)多个密钥是否可以具有相同的排名?如果是这样,那么select(r)会回来什么?

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

enter image description here

谢谢!

4 个答案:

答案 0 :(得分:3)

你的问题实际上归结为:“关于AVL树,通常如何定义术语'等级'?” (并且,可能,'select'通常也是如何定义的。)

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

“选择”基本上相反 - 您获得了特定的排名,并且需要检索指向指定节点(或该节点的密钥)的指针。

两个注意事项:首先,由于这些都根本不修改树,因此使用什么形式的平衡(例如,AVL与红/黑)没有实际区别;就此而言,没有平衡的树也是等同的。其次,如果你需要经常这样做,你可以通过在每个节点上添加一个额外的字段来记录其左边有多少个节点,从而大大提高速度。

答案 1 :(得分:1)

Rank是左子树中的节点数加1,并且是针对每个节点计算的。我认为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));
        }
}

答案 2 :(得分:0)

这是我编写的代码,并且可以很好地用于AVL Tree以获取特定值的等级。差异只是你使用一个节点作为参数,我使用一个键参数。你可以按自己的方式修改它。示例代码:

    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()来执行这段代码。

答案 3 :(得分:-1)

这就是我所做的。在我的程序中,元素的等级被定义为1+(没有大于该元素的元素)。你可以在这里注意到元素不需要存在于树中。

查找排名的算法:

1.在树结构中,跟踪包含根的子树中的元素的数量。因此,树的头部将包含树中的总元素。

2.将元素与节点进行比较,如果它小于节点,那么(右子元素中有1个元素)元素大于关键元素。将它添加到总数并递归搜索左孩子的元素。

3.如果元素大于根节点,则只需在右子节点中递归搜索元素。(无需添加任何内容,因为我们忽略了左侧树,其中所有元素都小于给定键)

4.当您发现元素已达到null时,终止算法。

给定程序不返回大于给定键的元素。 1+返回的值是等级。

代码段:

int AVLUtils::rank(Node *root,long long val)
  {
    int n_ele_greater=0;
    int rank =0;

    if(root == NULL)
    return 0;
   if(val < root->key)
     {
    n_ele_greater = 1+this->n_elements(root->right_child)+this->rank(root->left_child,val);
     }
   else if(val > root->key)
     {
    n_ele_greater=this->rank(root->right_child,val);
    }

    else if(val == root->key)
    {
    return(this->n_elements(root->right_child));
    }
    return(n_ele_greater);
   }

希望这会有所帮助:)