【问题标题】:OOP: inheritance with recursive class definitionOOP:具有递归类定义的继承
【发布时间】:2016-08-28 15:02:05
【问题描述】:

我(递归地)定义了一个用于实现二叉树的类(在 Java 中):

class BinaryTree {
    protected int key;
    protected BinaryTree left, right;

    // some methods...
}

我想从中实现一个二叉搜索树,像这样:

class BinarySearchTree extends BinaryTree {
    // ...

    public BinarySearchTree search(int x) {
        if (x == key)
            return this;
        if (x < key)
            if (left != null)
                return left.search(x);  // (*)
        else
            if (right != null)
                return right.search(x); // (*)
        return null;
    }
}

当然,标有// (*) 的行不会编译,因为leftright 只是BinaryTrees,没有任何search() 方法。

所以我想知道是否有一种方法可以从BinaryTree 超类定义BinarySearchTree,而leftright 实际上是BinarySearchTrees。

或者也许有更好的方法来实现二叉树和 搜索 之间的关系:我应该定义一个单独的 Node 类吗?我应该使用模板吗?我应该完全避免递归定义吗? ...

【问题讨论】:

  • 这里有两个单独的类有什么意义?为什么不直接将 search() 方法放在 BinaryTree 中而忘记 BinarySearchTree?
  • 是的,但是在未组织为二叉 search 树的二叉树中允许 search() 方法将是“危险的”,因为当树长大了:BinaryTree 搜索将是蛮力的,而 BinarySearchTree 保证最多是对数的。但这更多是关于算法和数据结构而不是 OOP :)
  • 一个可能比泛型解决方案更简洁的设计是使二叉树成为一个接口,并制作一个普通的二叉树实现以及二叉搜索树。

标签: java class oop inheritance recursion


【解决方案1】:

您可以使用递归泛型。

定义一个递归泛型类型变量,比如B

class BinaryTree<B extends BinaryTree<B>> {

并使您的字段成为这种类型:

protected B left, right;

然后定义:

class BinarySearchTree extends BinaryTree<BinarySearchTree> {

现在leftright 也是BinarySearchTree 类型,允许您调用left.searchright.search

【讨论】:

  • 我对泛型一无所知(两个月前我刚从 C++ 转过来),但您的解决方案可能正是我想要的。谢谢。
  • 我能看到的唯一缺点是,对于普通的BinaryTrees,您必须输入稍微冗长的BinaryTree&lt;BinaryTree&gt;
  • @qxz 那将是一个原始类型。是的,它相当丑陋。
  • 天哪,你是对的......甚至可以提供非原始类型参数吗?
  • @qxz erm 不确定。我主要是尽量避免递归泛型。可能带有类型变量。或者,将 BinaryTree 类抽象化,永远不要直接处理该类型。
【解决方案2】:

我觉得BinaryTreeNode 应该被创建为BinaryTree.java 的内部类。 BinaryTreeNode 可以有int data,以及leftright 节点的两个BinaryTreeNode 类型的引用

BinaryTree.java 应该有一个 BinaryTreeNode 类型的引用,这将是树的根。

现在BinarySearchTree extends BinaryTree 看起来不错,您可以在其中包含一个方法,如下签名。

BinaryTreeNode `search( int k, BinaryTreeNode root)`

现在您可以定义递归方法了。

请参阅带有基本骨架的示例代码。

BinaryTreeNode.java

public class BinaryTreeNode {

    private int data;
    private BinaryTreeNode left, right;

    public BinaryTreeNode(int data) {
        this.setData(data);
    }

    public BinaryTreeNode getLeft() {
        return left;
    }

    public void setLeft(BinaryTreeNode left) {
        this.left = left;
    }

    public BinaryTreeNode getRight() {
        return right;
    }

    public void setRight(BinaryTreeNode right) {
        this.right = right;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

}

BinaryTree.java

public class BinaryTree {
    protected BinaryTreeNode root;

    // other basic methods needed for creating the Binary tree.
}

BinarySearchTree.java

public class BinarySearchTree extends BinaryTree {
    public BinaryTreeNode search(int k) {
        return search(k, root);
    }

    private BinaryTreeNode search(int k, BinaryTreeNode root) {
        if (root.getData() == k) {
            return root;
        }
        if (root.getData() < k) {
            return search(k, root.getRight());
        } else {
            return search(k, root.getLeft());
        }
    }
    // add other methods needed for creating the Binary search tree.
    // also override the methods which needs to be modified for their behavior
    // for binary search tree
}

【讨论】:

  • 但是等等:BinaryTreeNodes、leftright 没有任何 search() 方法,对吧?
  • @George,BinaryTreeNode 没有搜索方法。 BinarySearchTree 扩展了 BinaryTree,它将包含搜索方法。 BinaryTree 包含对 BinaryTreeNode 对象的引用。
  • 哦,现在我明白了:所以我必须打电话给search(x, left);。好的,我想这也可以,谢谢!
  • @George,等一下,让我把实际代码放在我的答案中,希望它有助于澄清我的意思
  • 我已经添加了基本代码,希望对您有所帮助
猜你喜欢
  • 2014-09-02
  • 2017-12-23
  • 2016-03-18
  • 2022-11-27
  • 2018-04-14
  • 2016-04-04
  • 2020-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多