Java中的二叉搜索树迭代上限方法

时间:2012-03-04 23:04:49

标签: java

我正在为一堂课我正在努力解决问题。它涉及到二进制搜索树中添加方法:http://algs4.cs.princeton.edu/32bst/BST.java.html

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

到目前为止,这是我的代码。我理解我应该实现的算法的基础知识,但我发现实际上我很难将其包裹起来。

提前感谢您提供的任何帮助。

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;
}

编辑:我遇到的主要问题是如何处理第一个之后的迭代。根据我的书,“如果给定的密钥大于BST根部的密钥, 然后是钥匙的上限(BST中最大的钥匙更大 等于或等于键)必须在正确的子树中。如果关键是 小于根的关键,然后关键的上限可以 在左子树;如果不是(或者如果键等于键 在根),然后根的键是键的上限。“我不知道如何在循环中处理它。

2 个答案:

答案 0 :(得分:2)

您的代码是一个良好的开端。但你的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; }

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

答案 1 :(得分:0)

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

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); 
} 

更改ceilng(),以便递归调用是一种“累加器”类型的尾调用。通过传递迄今为止完成工作的其他参数来完成此操作。

当cmp&lt;时,null或节点作为x.left传递。到目前为止“积累”的是在这个条件测试中找到的大于项目的节点x。

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

在cmp&gt;的另一个条件测试中; 0,尾部调用,没有新的“累积”工作,因为x小于项目,如果x.right为null,则不用于决定返回值。

注意如果我们在修改的天花板(x,键,更大)函数中将“累积的x”传递给“更大”会发生什么。在此修改的函数中,条件“if(x == null)return null”被“if(x == null)return large”替换,并且在第一次递归调用之后删除所有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); 
}

现在函数是尾递归的,可以进一步转换为迭代循环形式。

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;
}