07.Java数据结构与算法之~二叉树的查找与删除

07.Java数据结构与算法之~二叉树的查找与删除

本文是上一篇文章的后续,详情请点击该链接

二叉树-查找指定结点

使用前序,中序,后序的方式来查询指定的结点

前序查找思路:

       1.先判断当前结点是否等于要查找的,如果是相等,则返回当前结点

       2.如果不等,则判断当前结点的左子结点是否为空,如果不为空,则递归前序查找

       3.如果左递归前序查找,找到结点,则返回。否则继续判断当前结点的右子结点是否为空,如果不空,则继续向右递归前序

中序查找思路:

       1.判断当前结点的左子结点是否为空,如果不为空,则递归中序查找

       2.如果找到则返回,如果没找到,就和当前结点比较,如果是则返回当前结点,否则继续进行右递归的中序查找

       3.如果右递归中序查找找到,就返回,否则返回null

后序查找思路:

       1.判断当前节点的左子结点是否为空,如果不为空,则递归后序查找

       2.如果找到就返回,如果没有找到,就判断当前结点的右子结点是否为空。如果不为空,则右递归进行后序查找,如果找到就返回。

       3.如果左右结点都没有找到,就和当前结点进行比较,找到就返回,否则返回Null。

代码实现:

补充Tree接口

       注:遍历方法在上一篇文章已经实现了,详情请点击上方链接,这篇文章就不重复叙述了。
       不过在文章的最下面,会把完整的代码最终再发一次

public interface Tree {
    //构建树
    void CreateBinaryTree(Object tree, Object left, Object right);
    //先序遍历
    void PreOrder();
    //中序遍历
    void InfixOrder();
    //后序遍历
    void PostOrder();

    //前序查找
    Object preOrderSearch(Object root);
    //中序查找
    Object infixOrderSearch(Object root);
    //后序查找
    Object postOrder(Object root);
}

BinaryTree实现类

    //前序查找
    @Override
    public Object preOrderSearch(Object root) {
        Object res = null;
        //判断二叉树是否为空
        if(root != null) {
            //比较当前是不是
            if (this.root == root) {
                return this;
            }
            //判断当前节点左子结点是否为空,如果不为空,则递归前序查找
            //如果左递归找到则返回
            if(this.left != null){
                 res = left.preOrderSearch(root);
            }
            //判断左递归是否找到,找到就返回,没找到就继续右递归
            if(res != null){
                return res;
            }
            //如果左递归没找到,就继续右递归查找
            if(this.right != null){
                res = right.preOrderSearch(root);
            }
        }else{
            throw new NullPointerException();
        }
        return res;
    }
    //中序查找
    @Override
    public Object infixOrderSearch(Object root) {
        Object res = null;
        //判断二叉树是否为空
        if(root != null) {
            //判断当前节点左子结点是否为空,如果不为空,则递归前序查找
            //如果左递归找到则返回
            if(this.left != null){
                res = left.preOrderSearch(root);
            }
            //判断左递归是否找到,找到就返回,没找到就继续比较当前结点
            if(res != null){
                return res;
            }
            //比较当前是不是
            if (this.root == root) {
                return this;
            }
            //如果左递归没找到,就继续右递归查找
            if(this.right != null){
                res = right.preOrderSearch(root);
            }
        }else{
            throw new NullPointerException();
        }
        return res;
    }
    //后序查找
    @Override
    public Object postOrderSearch(Object root) {
        Object res = null;
        //判断二叉树是否为空
        if(root != null) {
            //左递归查找,如果左递归找到则返回
            if(this.left != null){
                res = left.preOrderSearch(root);
            }
            //判断左递归是否找到,找到就返回,没找到就继续右递归
            if(res != null){
                return res;
            }
            //如果左递归没找到,就继续右递归查找
            if(this.right != null){
                res = right.preOrderSearch(root);
            }
            //比较当前是不是
            if (this.root == root) {
                return this;
            }
        }else{
            throw new NullPointerException();
        }
        return res;
    }

    //重写toString
    @Override
    public String toString() {
        return (String) root;
    }

测试类

        //前序查找
        Object preOrderSearch =  A.preOrderSearch("E");
        System.out.println(preOrderSearch);

        //中序查找
        Object infixOrderSearch = A.infixOrderSearch("G");
        System.out.println(infixOrderSearch);

        //后序查找
        Object postOrderSearch = A.postOrderSearch("A");
        System.out.println(postOrderSearch);

二叉树-删除结点

思路:

       1.因为我们的二叉树是单向的,所以我们是判断当前节点的子结点是否需要删除节点,而不能去判断当前这个结点是不是需要删除的节点

       2.如果当前结点的左子树不为空,并且左子结点就是需要删除的结点,就将this.left=null

       3.如果当前结点的右子结点不为空,并且右子结点就是要删除的结点,就将this.right=null

       4.如果2,3都没有删除结点,那么就需要向左子树进行递归删除

       5.如果左子树没有成功,就递归右子树

补充Tree接口

    //删除结点
    void remove(Object root);

BinaryTree实现类

  //递归删除结点
    //1.如果删除的结点是叶子结点,则删除该结点
    //2.如果删除的结点是非叶子结点,则删除该子树
    @Override
    public void remove(Object root) {
        //判断二叉树是否为空
        if(root != null){
            //如果当前结点的左子结点不为空,并且左子结点就是要删除的结点,那么就置空并返回
            if(left != null && left.root == root){
                left = null;
                return;
            }
            //如果当前结点的右子结点不为空,并且右子结点就是要删除的结点,那么就置空并返回
            if(right != null && right.right == root){
                right = null;
                return;
            }
            //如果都没有就向左子树递归进行删除
            if(left != null){
                left.remove(root);
            }
            //如果左子树递归没删除就向右子树递归删除
            if(right != null){
                right.remove(root);
            }
        }else{
            throw new NullPointerException();
        }
    }

最终代码

Tree接口

public interface Tree {
    //构建树
    void CreateBinaryTree(Object tree, Object left, Object right);
    
    //先序遍历
    void PreOrder();
    //中序遍历
    void InfixOrder();
    //后序遍历
    void PostOrder();

    //前序查找
    Object preOrderSearch(Object root);
    //中序查找
    Object infixOrderSearch(Object root);
    //后序查找
    Object postOrderSearch(Object root);

    //删除结点
    void remove(Object root);
}

BinaryTree实现类

public class BinaryTree implements Tree{
    private BinaryTree left;    //左子树
    private BinaryTree right;   //右子树
    private Object root;        //根结点
    int count = 0;
    //-------构造传值-------
    public BinaryTree(Object data){
        root =  data;
    }
    @Override
    //-------构建树-------         为了兼容接口统一Object
    public void CreateBinaryTree(Object tree, Object left, Object right){
        //强制转换
        BinaryTree Tree = (BinaryTree) tree;
        Tree.left = (BinaryTree)left;
        Tree.right = (BinaryTree)right;
    }

    //-------先序遍历-------
    @Override
    public void PreOrder() {
        //判断二叉树是否为空
        if(root != null){
            System.out.print(root + " ");
            //判断左子节点是否为空
            if(left != null){
                left.PreOrder();
            }
            if(right != null){
                right.PreOrder();
            }
        }else{
            //说明树为空,空指针异常
            throw new NullPointerException();
        }
    }
    //-------中序遍历-------
    @Override
    public void InfixOrder() {
        //判断二叉树是否为空
        if(root != null){
            //判断左子节点是否为空
            if(left != null){
                left.InfixOrder();
            }
            System.out.print(root + " ");
            if(right != null){
                right.InfixOrder();
            }
        }else{
            //说明树为空,空指针异常
            throw new NullPointerException();
        }
    }
    //-------后序遍历-------
    @Override
    public void PostOrder() {
        //判断二叉树是否为空
        if(root != null){
            //判断左子节点是否为空
            if(left != null){
                left.PostOrder();
            }
            if(right != null){
                right.PostOrder();
            }
            System.out.print(root + " ");
        }else{
            //说明树为空,空指针异常
            throw new NullPointerException();
        }
    }

    //前序查找
    @Override
    public Object preOrderSearch(Object root) {
        Object res = null;
        //判断二叉树是否为空
        if(root != null) {
            //比较当前是不是
            if (this.root == root) {
                return this;
            }
            //判断当前节点左子节点是否为空,如果不为空,则递归前序查找
            //如果左递归找到则返回
            if(this.left != null){
                 res = left.preOrderSearch(root);
            }
            //判断左递归是否找到,找到就返回,没找到就继续右递归
            if(res != null){
                return res;
            }
            //如果左递归没找到,就继续右递归查找
            if(this.right != null){
                res = right.preOrderSearch(root);
            }
        }else{
            throw new NullPointerException();
        }
        return res;
    }
    //中序查找
    @Override
    public Object infixOrderSearch(Object root) {
        Object res = null;
        //判断二叉树是否为空
        if(root != null) {
            //判断当前节点左子节点是否为空,如果不为空,则递归前序查找
            //如果左递归找到则返回
            if(this.left != null){
                res = left.preOrderSearch(root);
            }
            //判断左递归是否找到,找到就返回,没找到就继续比较当前节点
            if(res != null){
                return res;
            }
            //比较当前是不是
            if (this.root == root) {
                return this;
            }
            //如果左递归没找到,就继续右递归查找
            if(this.right != null){
                res = right.preOrderSearch(root);
            }
        }else{
            throw new NullPointerException();
        }
        return res;
    }
    //后序查找
    @Override
    public Object postOrderSearch(Object root) {
        Object res = null;
        //判断二叉树是否为空
        if(root != null) {
            //左递归查找,如果左递归找到则返回
            if(this.left != null){
                res = left.preOrderSearch(root);
            }
            //判断左递归是否找到,找到就返回,没找到就继续右递归
            if(res != null){
                return res;
            }
            //如果左递归没找到,就继续右递归查找
            if(this.right != null){
                res = right.preOrderSearch(root);
            }
            //比较当前是不是
            if (this.root == root) {
                return this;
            }
        }else{
            throw new NullPointerException();
        }
        return res;
    }
    //递归删除结点
    //1.如果删除的结点是叶子结点,则删除该结点
    //2.如果删除的结点是非叶子结点,则删除该子树
    @Override
    public void remove(Object root) {
        //判断二叉树是否为空
        if(root != null){
            //如果当前结点的左子结点不为空,并且左子结点就是要删除的结点,那么就置空并返回
            if(left != null && left.root == root){
                left = null;
                return;
            }
            //如果当前结点的右子结点不为空,并且右子结点就是要删除的结点,那么就置空并返回
            if(right != null && right.right == root){
                right = null;
                return;
            }
            //如果都没有就向左子树递归进行删除
            if(left != null){
                left.remove(root);
            }
            //如果左子树递归没删除就向右子树递归删除
            if(right != null){
                right.remove(root);
            }
        }else{
            throw new NullPointerException();
        }
    }

    //重写toString
    @Override
    public String toString() {
        return (String) root;
    }
}

Test测试类

public class Test {
    public static void main(String[] args) {
        Tree A = new BinaryTree("A");
        Tree B = new BinaryTree("B");
        Tree C = new BinaryTree("C");
        Tree D = new BinaryTree("D");
        Tree E = new BinaryTree("E");
        Tree F = new BinaryTree("F");
        Tree G = new BinaryTree("G");

        A.CreateBinaryTree(A,B,C);  //定义A的两个子节点
        A.CreateBinaryTree(B,D,E);  //定义B的两个子节点
        A.CreateBinaryTree(C,F,G);  //定义C的两个子节点

        //前序遍历
        A.PreOrder();   System.out.println();
        //中序遍历
        A.InfixOrder(); System.out.println();
        //后序遍历
        A.PostOrder();  System.out.println();

        //前序查找
        Object preOrderSearch =  A.preOrderSearch("E");
        System.out.println(preOrderSearch);

        //中序查找
        Object infixOrderSearch = A.infixOrderSearch("G");
        System.out.println(infixOrderSearch);

        //后序查找
        Object postOrderSearch = A.postOrderSearch("A");
        System.out.println(postOrderSearch);
        //删除测试
        A.remove("D");
        A.PreOrder();
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章