当前位置: 首页 > 知识库问答 >
问题:

递归地检索二叉搜索树的子集

史飞尘
2023-03-14

对于我用私有字段实现的二叉树对象

X key;
Y value;
Tree<X,Y> left;
Tree<X,Y> right;

我有一个方法公共树 子集(X startKey,X endKey) ,它需要返回一个树,包括具有startKey的节点和具有endKey的节点之间的所有键及其相应值。这个方法也需要使用递归来执行。

我遇到的问题是,我无法找到一种方法来获得一个以EndKey结尾的树(可能看起来像一个LinkedList),而不包括EndKey.leftEndKey.Right。我想我应该首先在根的左树或右树上递归调用方法,这取决于startKey是大于还是小于根键,所以:

if (this.key.compareTo(startKey) < 0) this.right.subset(startKey, endKey);
else if (this.key.compareTo(startKey > 0) this.right.subset(startKey, endKey);

这将一直在树中导航,直到到达包含键startkey的节点。当我到达这一点时,我将this复制到一个新树,这样我就可以避免编辑原始树。这个新树具有以startkey为根的节点,然后具有与原始树相同的子节点。

这就是我被困的地方。我知道我必须处理的问题是导航到EndKey,确保停在那里,不包括EndKey.leftEndKey.right,并且即使方法从递归调用中“展开”,也要正确返回子集。我在想,如果我想停止在EndKey,我将不得不以某种方式保留对其父节点的引用,这样我就可以将父节点的左或右子节点设置为键/值对,以便切断EndKey的其馀子节点。但是,由于我没有节点对象,也不能添加任何方法或构造函数,我不知道如何维护对父树的引用。我也不知道如何在维护startkey作为新树的根的同时尝试实现这一点。

换句话说,我想我已经设法得到了一个树的子集,它从一个较低的层次开始,一直延续到原始树的底部。我如何递归地消除我不想要的底部的孩子并返回我的新子集?

共有1个答案

郜德容
2023-03-14

如果您将其视为一个视图,实际上并没有将其删除,您只是将方法限制在子集的范围内。例如,在使用iterator()时,子映射只有自己的iterator实现,它从子映射的下限开始,并且在达到上限时返回hasNext()==false。用户不会注意到他实际上是在迭代原始树,因为它是完全隐藏的。我希望这个例子给你一个关于它的想法。

public interface Tree<X, Y> extends Iterable<Tree<X, Y>> {
    X getKey();
    X getValue();
    Tree<X, Y> floor(X key);
    Tree<X, Y> ceiling(X key);
    Tree<X, Y> subTree(X lo, X hi);
    // ...
}

public class TreeImpl<X, Y> implements Tree<X, Y> {
    final X key;
    Y value;
    TreeImpl<X, Y> left, right;

    public TreeImpl(X key, Y value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public Iterator<Tree<X, Y>> iterator() {
        return new TreeItr();
    }

    // Iterator starting at the most left to the most right;
    private class TreeItr implements Iterator<Tree<X, Y>> {
        // ...
    }

    @Override
    public Tree<X, Y> subTree(X lo, X hi) {
        return new SubTree<>(this, lo, hi);
    }

    private static class SubTree<X, Y> implements Tree<X, Y> {
        final Tree<X, Y> backing;
        final X lo, hi;

        public SubTree(Tree<X, Y> backing, X lo, X hi) {
            this.backing = backing;
            this.lo = lo;
            this.hi = hi;
        }

        @Override
        public Iterator<Tree<X, Y>> iterator() {
            return new SubTreeItr(backing.ceiling(lo), backing.floor(hi))
        }

        // Iterator starting at 'from' and returning 'hasNext() == false' after 'to'
        // has returned
        private class SubTreeItr implements Iterator<Tree<X, Y>> {
            final Tree<X, Y> from, to;

            public SubTreeItr(Tree<X, Y> from, Tree<X, Y> to) {
                this.from = from;
                this.to = to;
            }

            //...
        }

        @Override
        public Tree<X, Y> subTree(X lo, X hi) {
            // Check if lo > this.lo && hi < this.hi
            return new SubTree<>(backing, lo, hi);
        }
    }
}
 类似资料:
  • 我试图为我的BST做一个递归加法。public add方法接受一个int参数,private方法接受相同的int和一个节点。这是我目前掌握的代码 我经常得到空指针,也尝试过调试,但我的逻辑中有一些我看不到的缺陷。

  • 我正在用python开发一个二叉查找树。但是我的检索方法并不像我希望的那样工作。只有当我想检索根节点时,它才返回正确的值,对于所有其他节点,它都不返回任何值。 下面是我的节点类的代码: 我的二叉树代码: 所以Bintree中的最后一个方法为除Root之外的所有值返回Not,但它应该返回节点的值。 填充树:

  • 首先,这是家庭作业,所以把它放在外面。 我应该用特定的方法实现二叉查找树: void insert(字符串)、boolean remove(字符串)和boolean find(字符串)。 我已经能够成功地编程和测试插入,并找到方法,但我有困难与删除。 我的程序中发生的事情是,删除实际上并没有从树中删除任何东西,我相信这是因为它只引用当前节点的本地创建,但我可能错了。我认为我可以实现我需要测试的不同

  • 我试图验证二叉查找树。给定二叉树的根,确定它是否是有效的二叉查找树(BST)。 有效的BST定义如下: 节点的左子树只包含键小于节点键的节点。节点的右子树只包含键大于节点键的节点。左子树和右子树也必须是二叉搜索树。 https://leetcode.com/problems/validate-binary-search-tree/ 我正在使用递归解决方案,但它未能通过以下测试用例: 输入:[2,1

  • 问题内容: 我想在非二叉树中搜索一个项目(任何节点都可以有n个孩子)并立即退出递归。所讨论的节点可以是任何节点,而不仅仅是叶子。 这是我的代码,但我没有完整的搜索。 nNode包含: (是孩子) 和数据对象。 问题答案: 探索第一个孩子后,您不应该退出。您不需要循环前面的语句。

  • 由于它是一种递归方法,我无法弄清楚如何使用这些stg参数来存储树元素数据。我希望将stg保留在那里,以便学习如何将字符串数据存储在递归方法中。我该怎么做呢?(基本上我想摆脱诱惑1) 编辑:我尝试了stg+=root.getElement()+“”;带返回STG;但这并不奏效 输出示例“树的顺序遍历:1 2 3 X Y Z X Y Z”