二叉树的查找 具体实现

 可以把遍历的递归看成两部分 

一个是左递归 一个是右递归 两者互不打扰   各自递归各自

而不是我理解的 先递归了左边后 左边的再依次往上爬  再向右边

我不理解的一点      从A开始 一直左递归 所以打印了C之后 怎么会打印D(D是右子树)

这是因为 到B结点 在经历了sout  左递归后  会 再进行右递归 就打印了D  所以还是一个思想各个结点的递归互不干涉

代码




/**
 * title: 前中后序查找
 * @author 阿K
 * 2020年12月30日 下午11:49:44
 */
public class BinaryTreeDemo2 {

    public static void main(String[] args) {

        // 创建二叉树
        BinaryTree binaryTree = new BinaryTree();

        // 创建需要的结点
        HeroNode root = new HeroNode(1, "宋江");
        HeroNode node2 = new HeroNode(2, "吴用");
        HeroNode node3 = new HeroNode(3, "卢俊义");
        HeroNode node4 = new HeroNode(4, "林冲");
        HeroNode node5 = new HeroNode(5, "关胜");

        // 加入树
        root.setLeft(node2);
        root.setRight(node3);
        node3.setRight(node4);
        node3.setLeft(node5);
        binaryTree.setRoot(root);

        System.out.println("前序遍历,预计统计次数:4 ===> 查找顺序 1,2,3,5,4");
        binaryTree.perOrderSearch(5);

        System.out.println("中序遍历,预计统计次数:3 ===》 查找顺序 2,1,5,3,4");
        binaryTree.infixOrderSearch(5);
//
        System.out.println("后序遍历,预计统计次数:2 ===》 查找顺序 2,5, 4,3,1");
        binaryTree.postOrderSearch(5);
    }
}

// 定义二叉树
class BinaryTree {

    private HeroNode root;// 根节点

    public void setRoot(HeroNode root) {
        this.root = root;
    }

    // 前序遍历查找
    public HeroNode perOrderSearch(int no) {
        if (root != null) {
            return root.perOrderSearch(no);
        } else {
            return null;
        }
    }

    // 中序遍历查找
    public HeroNode infixOrderSearch(int no) {
        if (root != null) {
            return root.infixOrderSearch(no);
        } else {
            return null;
        }
    }

    // 后序遍历查找
    public HeroNode postOrderSearch(int no) {
        if (root != null) {
            return root.postOrderSearch(no);
        } else {
            return null;
        }
    }
}

// 定义节点
class HeroNode {
    private int no;
    private String name;
    private HeroNode left; // 左节点(默认为null)
    private HeroNode right; // 右节点(默认为null)

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

    /**
     * 须知:关于查找次数的统计
     * 为了有效的统计出正确的次数,应该放在 if(this.no == no) 上面
     * @param no
     * @return
     */

    // 节点的前序遍历查找
    public HeroNode perOrderSearch(int no) {//这里没有用static 这是因为否则就不能调用this了
        System.out.println("记录前序遍历查找,打印次数决定查找运行次数!");//前序遍历先打印
        // 比较当前节点是否
        if (this.no == no) {//先比较结点的序号   这个就是前序遍历的第一步 打印第一个访问到的结点的信息 这里替换成了return
            return this;
        }
        // 1、判断当前节点的左子节点是否为空,若不为空,则左递归前序查找
        // 2、若左递归前序查找,找到节点则返回
        HeroNode resNode = null;
        if (this.left != null) {//this指的是当前遍历到的结点  这个this的初值指的是根节点
            resNode = this.left.perOrderSearch(no);
        }
        if (resNode != null) {// 说明在左子树上找到了  如果经过上一个if语句
            // 上一个if语句结束 代表已经找到了最底部的左字节点
            //如果resNode是null
            /*
            代表这一步的resNode根本没被赋值 就是说根本没找到
             if (this.left != null) {
            resNode = this.left.perOrderSearch(no);
        }
        注意 调用perOrderSearch方法就是步进    因为每一次都是this.left调用  下一次就是this.this.left 这就是步进
        如果某次的this.left满足了这个条件
         if (this.no == no) {//先比较结点的序号   这个就是前序遍历的第一步 打印第一个访问到的结点的信息 这里替换成了return
            return this;
        }
        那么就会返回this   然后resNode就会得到this的值了
        如果不满足这个条件
          if (this.no == no) {//先比较结点的序号   这个就是前序遍历的第一步 打印第一个访问到的结点的信息 这里替换成了return
            return this;
        }
        也就是把从根节点的整个左子树都遍历完了 都没找到和指定序号相等的结点的序号 那么该方法也不会进入return  也就是说resNode不会被赋值(注意这个方法的最后是return resNode) 还是原来的null

             */
            return resNode;
        }
        //经过上面的两个if 此时的resNode就变成了树的最底层的左子节点
        //问题 那么在递归使用perOrderSearch的 时候 下面的代码不会执行吗
        //注意 只有在左递归结束的时候 perOrderSearch函数才会执行下面的右循环 因为一直进入了循环就无法向下执行了
        //错误了 并不是左递归结束才进行右递归 而是各个结点的递归是独立的  每次的左递归当然会进行右递归
        // 1、当前节点的右子树是否为空,若不为空,则右递归前序查找
        // 2、若右递归前序查找,找到节点则返回
        if (this.right != null) {
            //这个是查看右结点符不符合我们的编号
            resNode = this.right.perOrderSearch(no);
        }

        return resNode;
    }


    public   HeroNode  perOrderSearch1(int no){//为什么参数是 no 因为根据主方法 我们是根据英雄的编号查找
        System.out.println("前序查找的次数");
       //前序查找第一步  先打印根节点的信息
       if (this.no==no){  //和普通的前序不同 满足了条件才能打印
           return this ; //这里的打印就是return
       }

       HeroNode resNode=null;//最好要赋值初始值null
       //实现左递归  只有左子树不为空的时候 才能递归
        if (this.left!=null){
            resNode=this.left.perOrderSearch1(no);//
            //return resNode.perOrderSearch1(no);  这里错了 因为不能return 我这里的功能是递归 不是return
        }

        if (resNode!=null){//我觉得这个不仅仅是只有当左递归遍历到最后的时候 才会执行 而是每个结点都会执行
          //resNode被赋值了 说明就找到了
            return  resNode;
        }

        //可以看到 左递归和右递归是对称的代码
        if (this.right!=null){
            resNode=this.right.perOrderSearch1(no);//只有找得到 resNode才会被赋值 否则还是null
            //
        }

        return  resNode;


    }


        //自己写的中序遍历
    public  HeroNode infixOrderSearch1(int no){
        System.out.println("中序遍历的次数");  //注意这个不能写在这里
        //先左递归
        HeroNode resNode=null;
        if (this.left!=null){
            resNode=this.left.infixOrderSearch1(no);
        }

        if (resNode!=null){
            return  resNode;
        }
        System.out.println("中序遍历的次数");  //应该写在这里
        if (this.no==no){
            return  this;
        }

          //右递归
        if (this.right!=null){
            resNode=this.right.infixOrderSearch1(no);
        }
        return resNode;

    }















    // 节点的中序遍历查找
    public HeroNode infixOrderSearch(int no) {
        // 1、判断当前左节点是否为空,若不为空,则继续左递归中序遍历查找
        HeroNode resNode = null;
        if (this.left != null) {
            resNode = this.left.infixOrderSearch(no);
        }
        // 2、若不为空,则返回(既找到)
        if (resNode != null) {
            return resNode;
        }
        System.out.println("进入中序查找的次数统计");
        // 3、和当前节点进行比较,若是则返回
        if (this.no == no) {
            return this;
        }
        // 4、若不是,则继续右递归中序遍历查找
        if (this.right != null) {
            resNode = this.right.infixOrderSearch(no);
        }
        return resNode;
    }

    //自己写的后续遍历

    public  HeroNode postOrderSearch1(int no){
    HeroNode resNode=null;

    if(this.left!=null){
        resNode=this.left.postOrderSearch1(no);
    }

    if (resNode!=null){
        return  resNode;
    }

    if (this.right!=null){
        resNode=this.right.postOrderSearch1(no);
    }
        if (resNode!=null){
            return  resNode;
        }

        if (this.no==no){
            return  this;
        }
        //这里少了一个语句
        return  resNode;  //因为if里面的return 不能算作整个函数的return
    }











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值