Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
AVL树java的函数实现_Java_Avl Tree - Fatal编程技术网

AVL树java的函数实现

AVL树java的函数实现,java,avl-tree,Java,Avl Tree,问题: 我下面的代码(不工作): public K from(K K,int i)抛出未找到{ //重置堆栈 parentNode=新堆栈(); //返回值为k的节点 Node foundNode=findNode(k,根); 从helper返回(k,i,foundNode); } 公共K fromHelper(K,int i,Node v)抛出NotFound{ 如果(v==null){ 抛出新的NotFound(); } else如果(i==0){ 返回v.key; } //案例3:左树

问题:

我下面的代码(不工作):

public K from(K K,int i)抛出未找到{
//重置堆栈
parentNode=新堆栈();
//返回值为k的节点
Node foundNode=findNode(k,根);
从helper返回(k,i,foundNode);
} 
公共K fromHelper(K,int i,Node v)抛出NotFound{
如果(v==null){
抛出新的NotFound();
}
else如果(i==0){
返回v.key;
}
//案例3:左树存在
如果(v.left!=null){
如果(k.比较到(v.左键)<0){
从助手返回(k,i-1,v.左);
}
}
//案例2:右树存在
如果(v.right!=null){
从助手返回(k,i-1,v.right);
}
如果(!parentNode.isEmpty()){
//弹出父节点
节点父节点=parentNode.pop();
if(k.compareTo(parent.key)<0){
从助手返回(k,i-1,父级);
}
否则{
抛出新的NotFound();
}
}
否则{
抛出新的NotFound();
}
}

我完全不懂这个问题。我绝对无法找到一种方法来获得在O(log(n))时间内运行的算法。我能想到的唯一算法是按顺序遍历,将值存储在数组中,然后返回大于k的第I个最小键(如果存在),但显然这是最坏的情况O(n)。在过去的两天里,我一直在研究这个问题,我根本无法找到解决方案。教授给我的提示是在节点上添加一个size字段,它将告诉我子树v上的节点数,包括它本身。我的想法是尝试使用一个相对秩函数(给我节点值k相对于节点v的秩),但我想不出在O(log(n))时间内实现它的方法。如果您有任何帮助,我们将不胜感激。

在仔细考虑之后,我将为您提供一些代码片段,您可以使用这些代码片段自行开发该方法

前提条件:您确实必须向每个节点添加大小字段。每次插入和删除时都必须更新此大小字段。当然,当旋转一些子树时

有了这样的尺码信息,您应该能够做到:

public K from(K k, int i) {
    Node<K> foundNode = findNode(k, root);
    if (foundNode == null)
        throw new NotFound();
    return (i == 0)? foundNode.key : fromHelper(foundNode.right, i - 1);
}

关键技巧是确定左子树的剩余节点数(使用大小信息),然后根据剩余的节点数向左或向右走。

第一个问题:为什么
parentNode=new Stack()
这会重置某些内容?也许不应该这样做?另外,我认为算法是明确的。1) 找到值为k的节点。2) 如果
i==0
,则完成。3) 如果
i>0
,则必须首先搜索k节点的后续节点。在AVL树中,你知道在哪里可以找到它。唯一的事情:这个搜索必须是递归的!4) 一旦找到,让递归搜索后退
i-1次。那么您就有了请求的节点!搜索k节点的后续节点是什么意思?如果i>0,是否有三种情况?假设我们在节点v。首先检查左子树中的第一个节点是否大于k。如果是,那就去吧。否则,请选中右子树>k。如果是的话,就去那里。但如果假设v的左子树和右子树都不产生任何结果,会发生什么呢。然后我们还必须检查v的父项。这一步不会破坏我的O(log(n))运行时间吗?在二叉搜索树中,您总是知道k的所有左节点都小于k,而k的所有右节点都大于k。因此,在算法的每个步骤中,始终只需检查两个子节点中的一个。k的后继者可以这样找到:向右走一步,然后尽可能向左走一步。注意:我没有考虑整个算法。有很多步骤,你必须发展自己。也许它不像我在这里描述的那么简单。但这似乎是方向。假设您在AVL树中按此顺序插入以下键:37、46、71、85、68。68岁将是71岁的左撇子。如果我从(37,3)调用函数,那么它应该返回数字68。但是如果我不检查算法中的左子项,我将返回85,这是不正确的,因为函数需要返回大于k的第I个最小键。
public K from(K k, int i) {
    Node<K> foundNode = findNode(k, root);
    if (foundNode == null)
        throw new NotFound();
    return (i == 0)? foundNode.key : fromHelper(foundNode.right, i - 1);
}
private K fromHelper(Node<K> node, int i) {
    if (node == null || node.size() <= i)
        throw new NotFound();
    if (i == 0)
        return node.key;

    int sizeLeft = (node.left == null)? 0 : node.left.size();
    return (sizeLeft < i)? fromHelper(node.right, i - sizeLeft) : fromHelper(node.left, i - 1);
}