学习笔记-二叉树遍历、查找、删除

二叉树

树结构出现的原因:
在这里插入图片描述
在这里插入图片描述
二叉树示意图:
在这里插入图片描述
常用用语:
叶子节点:没有子节点的节点。
节点的权:节点值。
路径:从根节点找到该节点的一条路。
树的高度:也就是最大层数。

二叉树概念:每个节点最多只能有两个子节点称为二叉树。
二叉树的节点分为左子节点和右子节点。
在这里插入图片描述

三种遍历方式

前序遍历:先输出父节点,然后遍历左子树右子树。即先输出该节点,如果左子节点不为空,递归遍历左子节点,如果右子节点不为空,递归遍历右子节点。
中序遍历:先遍历左子树,然后输出父节点,然后遍历右子树。即如果左子节点不为空,递归遍历左子节点。输出该节点。如果右子节点不为空,递归遍历右子节点。
后序遍历:先遍历左子树右子树,最后输出父节点。即如果左子节点不为空,递归遍历左子节点,如果右子节点不为空,递归遍历右子节点。最后输出该节点。
区分三种遍历方式:看何时输出根节点,如果一开始就输出根节点,为前序遍历;如果最后输出根节点,为后序遍历;如果在中间输出根节点,为中序遍历。

代码示例

在这里插入图片描述

//二叉树
class BinaryTree{
    public Hero root;

    //前序遍历
    public void preOrder(){
       root.preOrder();
    }
    //中序遍历
    public void midOrder(){
        root.midOrder();
    }
    //后序遍历
    public void postOrder(){
        root.postOrder();
    }
}
//单个英雄节点
class Hero{
    public int no;
    public String name;
    public Hero left;
    public Hero right;

    //前序遍历
    public void preOrder(){
        System.out.println(this);
        if(this.left!=null){
            this.left.preOrder();
        }
        if(this.right!=null){
            this.right.preOrder();
        }
    }
    //中序遍历
    public void midOrder(){
        if(this.left!=null){
            this.left.midOrder();
        }
        System.out.println(this);
        if(this.right!=null){
            this.right.midOrder();
        }
    }
    //后序遍历
    public void postOrder(){
        if(this.left!=null){
            this.left.postOrder();
        }
        if(this.right!=null){
            this.right.postOrder();
        }
        System.out.println(this);
    }

    public Hero(int no, String name) {
        this.no = no;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Hero{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }
}

三种查找方式

前序查找:先看本节点是不是,是就直接返回,不是的话考虑是否有左子节点,有的话对左子节点递归查询,查到就直接返回,没查到时考虑是否有右子节点,有的话对右子节点递归查询,最后返回结果。
中序查找:考虑是否有左子节点,有的话对左子节点递归查询,查到就直接返回,没查到时比较本结点是不是,是就直接返回,不是的话考虑是否有右子节点,有的话对右子节点递归查询,最后返回结果。
后续查找:考虑是否有左子节点,有的话对左子节点递归查询,查到就直接返回,没查到时考虑是否有右子节点,有的话对右子节点递归查询,查到就直接返回,没查到比较本节点,最后返回结果。

代码

节点方法

//前序查找
    public Hero preOrderSearch(int no){
        //先找自己
        System.out.println("前序···");
        if(this.no==no){
            return this;
        }
        Hero resNode=null;
        //没找到就找左子树
        if(this.left!=null){
            resNode = this.left.preOrderSearch(no);
        }
        //左子树找到了就不用继续
        if(resNode!=null){
            return resNode;
        }
        //没找到就找右子树
        if(this.right!=null){
            resNode=this.right.preOrderSearch(no);
        }
        //不管找没找到都返回
        return resNode;
    }
    //中序查找
    public Hero midOrderSearch(int no){
        Hero resNode=null;
        if(this.left!=null){
            resNode = this.left.midOrderSearch(no);
        }
        if(resNode!=null){
            return resNode;
        }
        System.out.println("中序···");
        if(this.no==no){
            return this;
        }
        if(this.right!=null){
            resNode=this.right.midOrderSearch(no);
        }
        return resNode;
    }
    //后序查找
    public Hero postOrderSearch(int no){
        Hero resNode=null;
        if(this.left!=null){
            resNode = this.left.postOrderSearch(no);
        }
        if(resNode!=null){
            return resNode;
        }
        if(this.right!=null){
            resNode=this.right.postOrderSearch(no);
        }
        if(resNode!=null){
            return resNode;
        }
        System.out.println("后序···");
        if(this.no==no){
            return this;
        }
        return resNode;
    }

二叉树调用

//前序查找
    public Hero preOrderSearch(int no){
        if(root!=null){
            Hero hero = root.preOrderSearch(no);
            return hero;
        }else {
            return null;
        }
    }
    //中序查找
    public Hero midOrderSearch(int no){
        if(root!=null){
            Hero hero = root.midOrderSearch(no);
            return hero;
        }else {
            return null;
        }
    }
    //后序查找
    public Hero postOrderSearch(int no){
        if(root!=null){
            Hero hero = root.postOrderSearch(no);
            return hero;
        }else {
            return null;
        }
    }

删除节点的方法

删除的规则:如果是叶子节点,就直接删除该节点,如果不是叶子节点,就删除该子树。
思路:首先单独考虑空树和只有根节点的情况。其次,为了删除,我们应该定位到需删除节点的父节点,然后将父节点的左或右置空。所以默认判断的是根节点的下方节点。逻辑如下:如果左子节点不为空且就是要删除的,就把左子节点置空,返回;否则判断,如果右子节点不为空且是要删除的,把右子节点置空返回,否则,如果左子节点不为空,向左递归删除,然后向右递归删除。
存在的问题就是如果在左递归的过程中找到并删除了该节点,还会继续进行右递归,可以考虑用一个布尔值标记。

代码

节点代码

//删除节点
    public void delNode(int no){
        //是左子节点就删了
        if(this.left!=null && this.left.no==no){
            this.left=null;
            return;
        }
        //不是左子节点就看看是不是右子节点,是就删了
        if(this.right!=null&& this.right.no==no){
            this.right=null;
            return;
        }
        //都不是就向左递归查找删除
        if(this.left!=null){
            this.left.delNode(no);
        }
        //左边没有就找右边
        if(this.right!=null){
            this.right.delNode(no);
        }
    }

树代码

//删除节点
    public void delNode(int no){
        if(root!=null){
            if(root.no==no){
                root=null;
                return;
            }else {
                root.delNode(no);
            }
        }else {
            System.out.println("空树");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值