简体   繁体   English

使二进制搜索树通用

[英]Making a Binary search Tree Generic

public double sum(TreeNode root){
    Queue<TreeNode> queue = new ArrayDeque<>();
    double sum = 0;
    if(root!=null){
        queue.add(root);
    }
    while(!queue.isEmpty()){
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            TreeNode current = queue.remove();
            sum += current.value;
            if(current.leftChild!=null)
                queue.add(current.leftChild);
            if(current.rightChild!=null)
                queue.add(current.rightChild);
        }
    }
    return sum;
}

Now I need to implement a generic binary search Tree which can store in the value field of a node either a Character , an Integer or Double (if Character is a generic parameter of the Tree, then its ASCII code sum will be returned from the sum() method).现在我需要实现一个通用的二叉搜索树,它可以在节点的value字段中存储一个Character ,一个IntegerDouble (如果Character是树的一个通用参数,那么它的 ASCII 码和将从sum()返回sum()方法)。

And I need to perform various operations, like sum() of all the node's values (also insert, delete, search, maximum, minimum, etc.).我需要执行各种操作,例如所有节点值的sum() (还有插入、删除、搜索、最大值、最小值等)。

But I'm stuck on making my implementation generic.但我坚持让我的实现通用。 In the sum() method issues an error in the linesum()方法中,行中出现错误

sum += current.value;

Operator + cannot be applied to T.运算符 + 不能应用于 T。

How can I resolve it?我该如何解决?

Arithmetic operators can not be used with an arbitrary type, they are only applicable for numeric primitives and their wrapper types.算术运算符不能与任意类型一起使用,它们仅适用于数字基元及其包装类型。 So if you need to generify your logic, it not the way to go.因此,如果您需要生成您的逻辑,这不是可行的方法。

Instead, you can define a field of type BiFunction , which is a Function expecting two arguments, on the level of your Tree class (or whatever its name).相反,您可以在Tree类(或任何它的名称)的级别上定义一个BiFunction类型的字段,它是一个需要两个参数的函数 And use this BinaryOperator to accumulate the values of the nodes while traversing the tree.并使用此BinaryOperator在遍历树时累积节点的值。

Based on this quote:基于这个引用:

if Character is a generic parameter of the Tree, then its ASCII code sum will be returned from the sum() method如果Character是树的通用参数,那么它的 ASCII 码总和将从sum()方法返回

I assume that you need to keep the return type of the sum() method as double .我假设您需要将sum()方法的返回类型保持为double Since according to the requirements of your assignment only three generic types: Character , Integer or Double need to be supported, that's doable.由于根据您的作业要求,只需要支持三种泛型类型: CharacterIntegerDouble ,这是可行的。

For that the BiFunction mentioned above, can be defined as BiFunction<T,Double,Double> , where the first two generic parameters T and Double denote the types of incoming parameters of the function and the last type Double specifies the return type.对于上面提到的BiFunction ,可以定义为BiFunction<T,Double,Double> ,其中前两个泛型参数TDouble表示函数的传入参数类型,最后一个类型Double指定返回类型。 Here are examples of implementation of such function:以下是此类功能的实现示例:

BiFunction<Double, Double, Double> intMerger = Double::sum;
BiFunction<Integer, Double, Double> intMerger = (i, d) -> i + d;
BiFunction<Character, Double, Double> intMerger = (c, d) -> c + d;

Also, since you need to perform operations like binary search in your generic tree you need either define a generic parameter T as extending Comparable interface, or provide a Comparator ( otherwise you'll not be able to determine which value is greater/smaller while implementing a binary search, or finding min/max value ).此外,由于您需要在通用树中执行二进制搜索等操作,因此您需要将通用参数T定义为扩展Comparable接口,或者提供一个Comparator否则在实现时您将无法确定哪个值更大/更小二进制搜索,或查找最小/最大值)。 Since all the types that should be supported are comparable, you can use the first option and define the Generic parameter as T extends Comparable<T> , which means in plain English: something that knows how to compare itself.由于应支持的所有类型都是可比较的,因此您可以使用第一个选项并将 Generic 参数定义为T extends Comparable<T> ,这在简单的英语中意味着:知道如何比较自身的东西。

So as a result, you might have something like this:因此,您可能会有这样的结果:

public class MyTree<T extends Comparable<T>> {
    private final BiFunction<T, Double, Double> merger;

    public MyTree(BiFunction<T, Double, Double> merger) {
        this.merger = merger;
    }

    public double sum(TreeNode<T> root) {
        double total = 0;
        if (root == null) return total;
        
        Queue<TreeNode<T>> queue = new ArrayDeque<>();
        queue.add(root);
        
        while (!queue.isEmpty()) {
            int size = queue.size();
            TreeNode<T> current = queue.remove();

            total = merger.apply(current.value, total);
            
            if (current.leftChild != null) queue.add(current.leftChild);
            if (current.rightChild != null) queue.add(current.rightChild);
        }
        return total;
    }
    
    private static class TreeNode<T extends Comparable<T>> {
        private T value;
        private TreeNode<T> leftChild;
        private TreeNode<T> rightChild;
        
        // constructor, etc.
    }
}

Usage example:使用示例:

MyTree<Double> myTree1 = new MyTree<>(Double::sum);
MyTree<Integer> myTree2 = new MyTree<>((i, d) -> i + d);
MyTree<Character> myTree3 = new MyTree<>((c, d) -> c + d);

Note: if what I was telling about introducing a Function looks alien to you have a look at this tutorial provided by Oracle .注意:如果我所说的关于引入函数的内容对您来说看起来很陌生,请查看Oracle 提供的本教程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM