Java中的二叉搜索树迭代天花板法

Java中的二叉搜索树迭代天花板法,java,Java,我正在为课堂上的一个问题而努力,我一直在努力。它涉及到将一个方法添加到二元搜索树(在此处找到): 我需要开发一个迭代的上限方法,找到给定键的上限。它不能是递归的 这是到目前为止我的代码。我理解我应该实现的算法的基本原理,但我发现实际上我很难理解它 提前感谢您可能提供的任何帮助 public Key ceiling_i(Key key) { Node t = root; for(int i = 0; i < size(); i++){ int cmp = ke

我正在为课堂上的一个问题而努力,我一直在努力。它涉及到将一个方法添加到二元搜索树(在此处找到):

我需要开发一个迭代的上限方法,找到给定键的上限。它不能是递归的

这是到目前为止我的代码。我理解我应该实现的算法的基本原理,但我发现实际上我很难理解它

提前感谢您可能提供的任何帮助

public Key ceiling_i(Key key)
{
    Node t = root;
    for(int i = 0; i < size(); i++){
        int cmp = key.compareTo(t.key);
        if(cmp == 0) return t.key;
        else if(cmp < 0) t = t.left;
        else if(cmp > 0) t = t.right;

    }
    return null;
}
公钥上限\u i(密钥)
{
节点t=根;
对于(int i=0;i0)t=t,则为else;
}
返回null;
}
编辑:我面临的主要问题是如何处理第一次迭代之后的迭代。根据我的书,“如果给定的键大于BST根的键, 然后键的上限(BST中最大的键更大 大于或等于键)必须位于右侧子树中。如果键为 小于根部的键,则键的上限可以 位于左子树中;如果不是(或者如果key等于key
“我不知道如何在循环中处理这个问题。

您的代码是一个很好的开始。但是你的for循环对我来说没有意义

public Key ceiling_i(Key key)
{
    Node t = root;
    Node t largestVisited = null;
    while(t != null) {
        int cmp = key.compareTo(t.key);
        if(cmp == 0) return t.key;
        else if(cmp < 0) { largestVisited = Min(t, largestVisited); t = t.left; }
        else if(cmp > 0) { t = t.right; largestVisited = Min(t, largestVisited); }

    }
    return largestVisited;
}

Node Min(Node a, Node b) { return the node with the smaller key; }
公钥上限\u i(密钥)
{
节点t=根;
节点t最大访问量=null;
while(t!=null){
int cmp=键。比较(t键);
如果(cmp==0)返回t.key;
else如果(cmp<0){largestVisited=Min(t,largestVisited);t=t.left;}
else如果(cmp>0){t=t.right;largestVisited=Min(t,largestVisited);}
}
回访人数最多;
}
Node Min(Node a,Node b){返回具有较小键的节点;}

提示:您可以通过首先编写递归解决方案并注意到它是尾部递归的来派生此代码。通过重用已经存在的局部变量,尾部递归函数可以很容易地变成非递归函数。如果不再使用旧的堆栈帧,则无需打开另一个堆栈帧。

该书中的代码不是尾部递归的,因为第一个天花板()调用在返回之前对其进行了操作

private Node ceiling(Node x, Key key) {
    if (x == null) return null;
    int cmp = key.compareTo(x.key);
    if (cmp == 0) return x;
    if (cmp < 0) { 
        Node t = ceiling(x.left, key); 
        if (t != null) return t;
        else return x; 
    } 
    return ceiling(x.right, key); 
} 
专用节点天花板(节点x,钥匙){
如果(x==null)返回null;
int cmp=键。比较(x.key);
如果(cmp==0)返回x;
如果(cmp<0){
节点t=天花板(x.左键);
如果(t!=null)返回t;
否则返回x;
} 
返回天花板(x.右侧,钥匙);
} 
更改ceiling(),使递归调用成为尾部调用的“累加器”类型。通过传递包含到目前为止所做工作的其他参数来实现这一点

当cmp<0时,Null或节点作为x.left传递。到目前为止,“累积”的是一个大于此条件测试中发现的项节点x

在第一次递归调用之后的原始版本中,t要么为null,要么为某个树节点。如果t为null,则使用节点x。在修改版本中,将向x节点传递一个附加参数

在带有尾部调用的cmp>0的另一个条件测试中,没有新的“累积”功,因为x小于该项,并且如果x.right为null,则不用于确定返回值

请注意,如果我们在修改过的天花板(x,键,较大)函数中将“累积x”传递给“较大”,会发生什么。在这个修改过的函数中,条件“if(x==null)return null”被替换为“if(x==null)return biger”,并且在第一次递归调用之后删除所有的t值求值。对于第二个尾部调用,只需将null传递给更大的

因此,转换应如下所示:

private Node ceiling (Node x, Key key, Node larger) {
    if (x == null) return larger;
    int cmp = key.compareTo(x.key);
    if (cmp == 0) return x;
    if (cmp < 0) { 
        return ceiling(x.left, key, x); 
    } 
    return ceiling(x.right, key, null); 
}
私有节点上限(节点x,密钥,节点更大){
如果(x==null)返回较大值;
int cmp=键。比较(x.key);
如果(cmp==0)返回x;
如果(cmp<0){
返回天花板(x.左侧,钥匙,x);
} 
返回上限(x.right,key,null);
}
现在该函数是尾部递归的,可以进一步转换为迭代循环形式

private Node ceiling (Node x, Key key) {
    Node larger = null;
    while (x != null) {
        int cmp = key.compareTo(x.key);
        if (cmp == 0) return x;
        if (cmp < 0) {
            larger = x;
            x = x.left;
        } else {
            x = x.right;
        }
    }
    return larger;
}
专用节点天花板(节点x,钥匙){
节点较大=空;
while(x!=null){
int cmp=键。比较(x.key);
如果(cmp==0)返回x;
if(cmp<0){
较大=x;
x=x.左;
}否则{
x=x,右;
}
}
回报较大;
}

在这个解决方案中什么不起作用?当我们在没有孩子的叶子上找不到匹配项时,就会出现t==null的情况。这个答案与我的答案类似,如果它等于键,它会找到上限,但没有处理我在编辑中提到的问题。我编辑了我的代码来解释这个问题。我的旧代码只是在寻找一个精确的匹配项。我祈祷现在一切都是正确的。在《最大访问量》中,我记录了迄今为止发现的最好的天花板。好的,我做了另一次编辑。我现在一直在改进迄今为止发现的最好的天花板。我将其更正为尽可能小。天哪,这个代码会变得正确吗?