数据结构和算法(20)之二叉树查找与删除指定节点

学习数据结构和算法的日常Demo

查找二叉树中指定节点
查找要求
  • 编写前序查找,中序查找和后序查找的方法
  • 根据传入的value值,分别使用三种查找方式查找value对应的树节点
代码实现
public class TreeNode {
    private int value;
    private TreeNode left;
    private TreeNode right;

    public TreeNode(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "TreeNode{" +
                "value=" + value +
                '}';
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public TreeNode getLeft() {
        return left;
    }

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

    public TreeNode getRight() {
        return right;
    }

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

 // 前序遍历查找指定节点
    public TreeNode preSearch(int value) {
        // 先和根节点比较
        if (this.value == value) {
            return this;
        }
        // 从左子树开始递归查找
        TreeNode tree = null;
        if (this.left != null) {
            tree = this.left.preSearch(value);
        }
        if (tree != null) {
            // 说明左子树递归中找到了
            return tree;
        }
        // 从右子树开始递归查找
        if (this.right != null) {
            tree = this.right.preSearch(value);
        }
        return tree;
    }

    // 中序遍历查找指定节点
    public TreeNode infixSearch(int value) {
        // 从左子树开始递归查找
        TreeNode tree = null;
        if (this.left != null) {
            tree = this.left.infixSearch(value);
        }
        if (tree != null) {
            // 说明左子树递归中找到了
            return tree;
        }
        // 和根节点比较
        if (this.value == value) {
            return this;
        }
        // 从右子树开始递归查找
        if (this.right != null) {
            tree = this.right.infixSearch(value);
        }
        return tree;
    }

    // 后序遍历查找指定节点
    public TreeNode postSearch(int value) {
        // 从左子树开始递归查找
        TreeNode tree = null;
        if (this.left != null) {
            tree = this.left.postSearch(value);
        }
        if (tree != null) {
            // 说明左子树递归中找到了
            return tree;
        }
        // 从右子树开始递归查找
        if (this.right != null) {
            tree = this.right.postSearch(value);
        }
        if (tree != null) {
            // 说明右子树递归中找到了
            return tree;
        }
        // 和根节点比较
        if (this.value == value) {
            return this;
        }
        return tree;
    }
}    

public class BinaryTree {
    private TreeNode root;

    public TreeNode getRoot() {
        return root;
    }

    public void setRoot(TreeNode root) {
        this.root = root;
    }
// 前中后查找
    public TreeNode preSearch(int value) {
        if (root != null) {
            return root.preSearch(value);
        }
        return null;
    }

    public TreeNode infixSearch(int value) {
        if (root != null) {
            return root.infixSearch(value);
        }
        return null;
    }

    public TreeNode postSearch(int value) {
        if (root != null) {
            return root.postSearch(value);
        }
        return null;
    }
}

public class BinaryTreeDemo {
    public static void main(String args[]) {
        BinaryTree tree = new BinaryTree();
        TreeNode root = new TreeNode(33);
        TreeNode node1 = new TreeNode(18);
        TreeNode node2 = new TreeNode(63);
        TreeNode node3 = new TreeNode(77);
        TreeNode node4 = new TreeNode(51);
        TreeNode node5 = new TreeNode(9);
        TreeNode node6 = new TreeNode(24);
        TreeNode node7 = new TreeNode(100);
        // 构建树
        root.setLeft(node1);
        root.setRight(node2);
        node1.setLeft(node5);
        node1.setRight(node6);
        node2.setLeft(node4);
        node2.setRight(node3);
        node3.setRight(node7);
        // 创建根节点
        tree.setRoot(root);

        /*
                 33
           18           63
         9   24       51    77
                                100
         */
        System.out.println("前序查找:"+tree.preSearch(18));
        System.out.println("前序查找:"+tree.preSearch(180));
        System.out.println("中序查找:"+tree.infixSearch(63));
        System.out.println("后序查找:"+tree.postSearch(51));
   }
}

在这里插入图片描述

删除二叉树指定节点
删除要求
  • 根据传入的value值,删除value对应的树节点
  • 如果删除的节点是根节点,则整树置为空
  • 如果删除的节点是叶子节点,则删除该节点
  • 如果删除的节点是非叶子节点,则删除该子树
删除思路

在这里插入图片描述

代码实现
// TreeNode.class
 public void delete(int value) {
        // 如果当前节点的左子节点不为空,并且就是要删除的
        if (this.left != null && this.left.value == value) {
            this.left = null;
            return;
        }
        // 如果当前节点的右子节点不为空,并且就是要删除的
        if (this.right != null && this.right.value == value) {
            this.right = null;
            return;
        }
        // 向左子树继续递归
        if (this.left != null) {
            this.left.delete(value);
        }
        // 向右子树继续递归
        if (this.right != null) {
            this.right.delete(value);
        }
    }

// BinaryTree.class
public void delete(int value) {
        if (root != null) {
            // 判断root是否为要删除节点
            if (root.getValue() == value) {
                root = null;    // 置空
            } else {
                root.delete(value);
                System.out.println("删除成功!");
            }
        } else {
            System.out.println("树为空!");
        }
    }

// BinaryTreeDemo.class
  /*
                 33
           18           63
         9   24       51    77
                                100
         */
   	    System.out.println("删除前:");
        tree.preOrder();
        System.out.println();
        tree.delete(18);
        System.out.println("删除后:");
        tree.preOrder();

删除前(前序遍历):
TreeNode{value=33} TreeNode{value=18} TreeNode{value=9} TreeNode{value=24} TreeNode{value=63} TreeNode{value=51} TreeNode{value=77} TreeNode{value=100}
删除成功!
删除后(前序遍历):
TreeNode{value=33} TreeNode{value=63} TreeNode{value=51} TreeNode{value=77} TreeNode{value=100}

删除改进(存在bug)
  • 根据传入的value值,删除value对应的树节点
  • 如果删除的节点是根节点,则整树置为空
  • 如果删除的节点是叶子节点,则删除该节点
  • 如果删除的节点是非叶子节点,则进行如下判断:
    在这里插入图片描述
代码实现
// TreeNode.class
  // 递归删除节点
    // 如果是叶子节点,则删除该节点
    // 若非叶子节点,1.子节点只有一个,则该子节点替换之;
    // 2.有左右子节点,则左节点替换之(即右子节点成为该左节点的子节点)
    // 若是根节点,将树置空
    public void delete2(int value) {
        // 如果当前节点的左子节点不为空,并且就是要删除的
        if (this.left != null && this.left.value == value) {
            // 判断该左子节点(它)下面是否还包含左右子节点
            // 1.如果它的左右子节点均不为空,则让它的左子节点取代之,并且它的右子节点成为左子节点的新右子节点(bug-->如果它的左子节点本身有右子节点,导致强行覆盖)
            if (this.left.left != null && this.left.right != null) {
                this.left.left.right = this.left.right; // 会出现覆盖问题
                this.left = this.left.left;
            } else if (this.left.left == null || this.left.right == null){
                // 2.若它下面只有一个子节点,就进行该判断:有左加左,无左加右
                this.left = (this.left.left == null ? this.left.right : this.left.left);
            }else {
                // 3.当前节点的子节点下再无任何子树
                this.left = null;
            }
            return;
        }
        // 如果当前节点的右子节点不为空,并且就是要删除的
        if (this.right != null && this.right.value == value) {
            // 判断该左子节点(它)下面是否还包含左右子节点
            // 如果它的左右子节点均不为空,则让它的左子节点取代之,并且它的右子节点成为左子节点的右子节点
            if (this.right.left != null && this.right.right != null) {
                this.right.left.right = this.right.right;   // 出现覆盖问题
                this.right = this.right.left;
            } else if (this.right.left == null || this.right.right == null){
                // 若它下面只有一个子节点,就进行该判断:有左加加左,无左加右
                this.right = (this.right.left == null ? this.right.right : this.right.left);
            }else {
                this.right = null;
            }
            return;
        }
        // 向左子树继续递归
        if (this.left != null) {
            this.left.delete2(value);
        }
        // 向右子树继续递归
        if (this.right != null) {
            this.right.delete2(value);
        }
    }

// BinaryTree.class
 // 改进了对子树的删除
    public void delete2(int value) {
        if (root != null) {
            // 判断root是否为要删除节点
            if (root.getValue() == value) {
                root = null;    // 置空
            } else {
                root.delete2(value);
                System.out.println("删除成功!");
            }
        } else {
            System.out.println("树为空!");
        }
    }

// BinaryTreeDemo.class
 /*
                 33
           18           63
         9   24       51    77
                                100
         */
   	    System.out.println("删除前:");
        tree.preOrder();
        System.out.println();
        tree.delete2(18);
        System.out.println("删除后:");
        tree.preOrder();
        System.out.println(node5 + "的右节点为:" + node5.getRight());

删除前(前序遍历):
TreeNode{value=33} TreeNode{value=18} TreeNode{value=9} TreeNode{value=24} TreeNode{value=63} TreeNode{value=51} TreeNode{value=77} TreeNode{value=100}
删除成功!
删除后(前序遍历):
TreeNode{value=33} TreeNode{value=9} TreeNode{value=24} TreeNode{value=63} TreeNode{value=51} TreeNode{value=77} TreeNode{value=100}
< TreeNode{value=9}的右节点为:TreeNode{value=24} >

删除改进存在bug(如果左子节点本身有右子节点,会导致强行覆盖),待修复…
GitHub:数据结构和算法源代码
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值