Java 二叉搜索树类-删除、搜索、插入、删除和迭代器方法-迭代与递归

Java 二叉搜索树类-删除、搜索、插入、删除和迭代器方法-迭代与递归,java,recursion,binary-tree,Java,Recursion,Binary Tree,最近,我开始学习java中的二叉树,了解它们的应用以及如何利用它们。我在网上发现了这个BinaryTree类,我想实现它: public abstract class BinaryTree<E> implements Iterable<E> { protected class Node<T> { protected Node(T data) { this.data = data; } protected T dat

最近,我开始学习java中的二叉树,了解它们的应用以及如何利用它们。我在网上发现了这个BinaryTree类,我想实现它:

public abstract class BinaryTree<E> implements Iterable<E> {

protected class Node<T> {

    protected Node(T data) {
        this.data = data;
    }

    protected T data;
    protected Node<T> left;
    protected Node<T> right;
}

public abstract void insert(E data);
public abstract void remove(E data);
public abstract boolean search(E data);

protected Node<E> root;
}
公共抽象类二进制树实现了Iterable{
受保护类节点{
受保护节点(T数据){
这个数据=数据;
}
受保护的T数据;
左保护节点;
受保护的节点权限;
}
公开摘要无效插入(E数据);
公开摘要作废(E数据);
公共抽象布尔搜索(E数据);
受保护的节点根;
}
现在,我开始简单地为我的implemted类的头创建头:

public class BinarySearchTree<E extends Comparable<? super E>> extends BinaryTree<E> {

}

公共类BinarySearchTree递归的基本思想是对每个较小的问题应用一个函数,并将结果返回到调用堆栈中。例如,就树而言,contains/search方法是检查当前节点数据的结果,或者左子树包含元素,或者右子树包含元素。同样,对于insert,将节点与元素进行比较,然后递归地向右或向左插入,并在遇到空节点时立即分配一个新的叶节点

就效率而言,递归的开销是将更多的调用放在stacktrace上,从而可能产生StackOverflow

迭代通常更容易调试,因为您对每个步骤中的整个过程都有了解

尾部递归提高了效率,但我认为这不适用于二进制树方法。无论哪种方式,如果编写正确,两种实现的运行时效率都是相似的。如果子问题定义良好,IMO递归看起来更干净


下面是一个使用递归实现二进制树的示例。由于复杂性的原因,
remove
方法被省略了,但我添加了
toString
作为另一个例子

public class BinaryTree<E extends Comparable<? super E>> {

    protected class Node<T extends E> {
        protected T data;
        protected Node<T> left;
        protected Node<T> right;

        protected Node(T data) {
            this.data = data;
        }

        protected Node<T> insert(T data) {
            if (data.compareTo(this.data) <= 0) {
                if (left == null) {
                    this.left = new Node(data);
                } else {
                    this.left = this.left.insert(data);
                }
            } else {
                if (right == null) {
                    this.right = new Node(data);
                } else {
                    this.right = this.right.insert(data);
                }
            }

            return this;
        }

        protected boolean search(T data) {
            if (data.compareTo(this.data) == 0) {
                return true;
            }

            if (this.left != null && data.compareTo(this.data) <= 0) {
                return this.left.search(data);
            } else if (this.right != null && data.compareTo(this.data) > 0) {
                return this.right.search(data);
            }

            return false;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            String divider = ", ";

            if (this.left != null) {
                sb.append(this.left.toString()).append(divider);
            }

            sb.append(String.valueOf(this.data)).append(divider);

            if (this.right != null) {
                sb.append(this.right.toString()).append(divider);
            }

            if (sb.length() > divider.length() - 1) {
                sb.setLength(sb.length() - divider.length());
            }

            return sb.toString();
        }
    }

    protected Node<E> root;

    public Node<E> insert(E data) {
        if (root == null) this.root = new Node(data);
        else {
            this.root = this.root.insert(data);
        }
        return this.root;
    }

    public Node<E> remove(E data) {
        return null; // TODO: Implement this
    }

    public boolean search(E data) {
        return root != null && this.root.search(data);
    }

    @Override
    public String toString() {
        return String.valueOf(this.root);
    }
}

public-class-binarytree是一个可以应用递归的示例。@Jongware-我知道你在那里做了什么;)@板球007:这意味着你了解退出条件。我想我说效率时应该说得更清楚一点;我说的只是实现方法体所需的代码行。例如,我仍然不知道如何单独使用递归来完成每个方法的函数。@python-为什么代码行很重要?编程不像写论文,你不会根据完成一个程序所需的页数来评分,只要它工作正常。如果你想看到一个递归的解决方案,至少搜索和插入,我可以更新我的答案。因为我是一个入门级程序员,当涉及到效率时,行数很重要,因为效率的一部分包括解决问题所需的时间。我被告知使用递归而不是迭代可以轻松节省30行或更多的代码,这就是为什么我来到这里希望有人回答我的问题,而不是告诉我不要问它。@python-我添加了一个递归二进制树解决方案。代码行具有相当的可比性
remove
可能比我实现它所花费的时间少一点。
public class BinaryTree<E extends Comparable<? super E>> {

    protected class Node<T extends E> {
        protected T data;
        protected Node<T> left;
        protected Node<T> right;

        protected Node(T data) {
            this.data = data;
        }

        protected Node<T> insert(T data) {
            if (data.compareTo(this.data) <= 0) {
                if (left == null) {
                    this.left = new Node(data);
                } else {
                    this.left = this.left.insert(data);
                }
            } else {
                if (right == null) {
                    this.right = new Node(data);
                } else {
                    this.right = this.right.insert(data);
                }
            }

            return this;
        }

        protected boolean search(T data) {
            if (data.compareTo(this.data) == 0) {
                return true;
            }

            if (this.left != null && data.compareTo(this.data) <= 0) {
                return this.left.search(data);
            } else if (this.right != null && data.compareTo(this.data) > 0) {
                return this.right.search(data);
            }

            return false;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            String divider = ", ";

            if (this.left != null) {
                sb.append(this.left.toString()).append(divider);
            }

            sb.append(String.valueOf(this.data)).append(divider);

            if (this.right != null) {
                sb.append(this.right.toString()).append(divider);
            }

            if (sb.length() > divider.length() - 1) {
                sb.setLength(sb.length() - divider.length());
            }

            return sb.toString();
        }
    }

    protected Node<E> root;

    public Node<E> insert(E data) {
        if (root == null) this.root = new Node(data);
        else {
            this.root = this.root.insert(data);
        }
        return this.root;
    }

    public Node<E> remove(E data) {
        return null; // TODO: Implement this
    }

    public boolean search(E data) {
        return root != null && this.root.search(data);
    }

    @Override
    public String toString() {
        return String.valueOf(this.root);
    }
}