1

请帮助一个困惑的新手。我目前正在练习使用 add、remove、contains 和 toString 等方法实现二叉搜索树。我可以实现该类以使用整数值,但我无法弄清楚如何在二叉搜索树上使用泛型。我想灵活一点,也想为我的二叉搜索树或者我的 Card 类使用字符串。

public class MyTree<E> {

    private class Node implements Comparable<E> {
        private E data;
        private Node left;
        private Node right;
        public Node(E data) {
            this.data = data;
        }
        public int compareTo(E other) { 
            return this.data.compareTo(other); //ERROR HERE 
                                               //(Cannot Find Symbol at method CompareTo(E))
        }
    }

    private Node root;
    private int size;

    public int getSize() {
        return size;
    }

    public void add(E value) {
        this.root = add(value, root);
    }

    private Node add(E value, Node currentRoot) {
        if (currentRoot == null) {
            Node temp = new Node(value);
            size++;
            return temp;
        } else {
            if (currentRoot.compareTo(value) > 0)
                currentRoot.left = add(value, currentRoot.right);
            else if (currentRoot.compareTo(value) < 0)
                currentRoot.right = add(value, currentRoot.right);
            return currentRoot;
        }
    }

我得到一个错误。

return this.data.compareTo(other);
                 ^
symbol: method compareTo(E)
location: variable data of type E
where E is a type-variable:
 E extends object declared in class MyTree

当我的 Node 类中有 compareTo(E other) 时,为什么找不到 compareTo。我在我的 Node 类中实现了 Comparable 接口,但我不知道为什么。我也尝试过使用 Comparable 工具,但这也不起作用。

4

2 回答 2

2

问题是您已将E其作为参数传递给Comparable但未定义。通常,实现的类Comparable将自身作为参数传递给Comparable(作为通用参数)。Comparable应该用于比较相同类型的实例。但是,如果您查看您的实现,您并没有比较此类的两个实例,您只是将您的类value的一个实例与以下add方法行中的另一个实例的字段进行比较:

if (currentRoot.compareTo(value) > 0)

你可以看到currentRootis 的 typeNode和 value 的 type E。这是一个错误的实现,因为如果你想要类型安全,你不应该比较不同类型的值(或者如果你想比较它们,它们不应该彼此相等,因为它们有不同的类型)所以为什么不你只是比较这两个values吗?

另一方面E是泛型类型,它不仅用于Node类,E也用于类的add方法中MyTree。所以E应该是类的通用参数,MyTree你应该让类的用户 决定他想要使用类MyTree的确切类型。另一个约束是应该实现的,因为我们想将类型的实例相互比较。EMyTreeEComparableE

最后,您的课程将更改为以下课程:

public class MyClassTree<E extends Comparable<E>> {
    private class Node {
        private E data;
        private Node left;
        private Node right;

        public Node(E data) {
            this.data = data;
        }
    }

    private Node root;
    private int size;

    public int getSize() {
        return size;
    }

    public void add(E value) {
        this.root = add(value, root);
    }

    private Node add(E value, Node currentRoot) {
        if (currentRoot == null) {
            Node temp = new Node(value);
            size++;
            return temp;
        } else {
            if (currentRoot.data.compareTo(value) > 0)
                currentRoot.left = add(value, currentRoot.right);
            else if (currentRoot.data.compareTo(value) < 0)
                currentRoot.right = add(value, currentRoot.right);
            return currentRoot;
        }
    }
}
于 2020-11-27T11:02:02.977 回答
1

您在 E 类型中调用 compareTo 方法 - 它没有此方法。通过实现接口,你的类继承了方法,而不是未知类型参数类。含义:您必须在 Node 类中创建自定义比较机制。

(注意:您也可以检查 E 是否实现了 Comparable,但这比较困难,并且在编译时可能无法实现。)

(注 2:如果您感到困惑,请认为 Comparable 意味着实现类的实例可以与 E 类型的对象进行比较。这甚至不是您想要的实现。)

于 2020-11-27T09:25:49.460 回答