• 26-二叉树的遍历查找和删除


    1. 遍历方式

    a. 先序遍历

    • 步骤 // 先访问根结点
      1. 访问根结点
      2. 先序访问左子树
      3. 先序访问右子树
    • 举例

    b. 中序遍历

    • 步骤 // 中间访问根结点
      1. 中序遍历左子树
      2. 访问根结点
      3. 中序遍历右子树
    • 举例

    c. 后序遍历

    • 步骤 // 最后访问根结点
      1. 后序遍历左子树
      2. 后序遍历右子树
      3. 访问根结点
    • 举例

    2. 查找结点

    3. 删除结点

    • 如果删除的结点是叶子结点,则删除该结点
    • 如果删除的结点是非叶子结点,则删除该子树

    ∵二叉树是单向的 ∴ 判断的应当是当前结点的子结点是否为待删结点,而不应该直接找待删结点。

    1. 待删结点编号恰为 root 结点的编号,则置空二叉树
    2. 如果当前结点的 左子结点不为空&&左子结点的编号为待删结点编号,直接将 this.left 置空,并将 待删结点 返回;
    3. 如果当前结点的 右子结点不为空&&右子结点的编号为待删结点编号,直接将 this.right 置空,并将 待删结点 返回;
    4. 如果 step2 和 step3 没有删除结点,就向左子树递归删除 // 若找到了就直接返回,以免再去右边做无用功;
    5. 如果 step4 还没把结点删除,就再向右子树递归删除

    4. 代码实现

    public class BinaryTreeDemo {
      public static void main(String[] args) {
        BiTree biTree = new BiTree();
        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.left = node2;
        root.right = node3;
        node3.right = node4;
        node3.left = node5;
        biTree.root = root;
        /*
        System.out.println("前序遍历:");
        biTree.preOrderBiTree(); // 1, 2, 3, 5, 4
        System.out.println("--------------");
        System.out.println("中序遍历:");
        biTree.midOrderBiTree(); // 2, 1, 5, 3, 4
        System.out.println("--------------");
        System.out.println("后序遍历:");
        biTree.postOrderBiTree(); // 2, 5, 4, 3, 1
        System.out.println("--------------");
        System.out.println("前序查找:");
        HeroNode node = biTree.preOrderSearch(5); // 4次
        System.out.println(node!=null ? node : "没找到");
        System.out.println("--------------");
        System.out.println("中序查找:");
        node = biTree.midOrderSearch(5); // 3次
        System.out.println(node!=null ? node : "没找到");
        System.out.println("--------------");
        System.out.println("后序查找:");
        node = biTree.postOrderSearch(5); // 2次
        System.out.println(node!=null ? node : "没找到");
        System.out.println("--------------");
        */
        System.out.println("删除结点5:" + biTree.deleteNode(5));
      }
    }
    
    class BiTree {
      public HeroNode root;
    
      // 前序遍历
      public void preOrderBiTree() {
        if (root != null) root.preOrderBiTree();
        else System.out.println("二叉树为空, 无法前序遍历");
     }
    
      // 中序遍历
      public void midOrderBiTree() {
        if (root != null) root.midOrderBiTree();
        else System.out.println("二叉树为空, 无法中序遍历");
     }
    
      // 后序遍历
      public void postOrderBiTree() {
        if (root != null) root.postOrderBiTree();
        else System.out.println("二叉树为空, 无法后序遍历");
      }
    
      // 前序查找
      public HeroNode preOrderSearch(int no) {
        if (root != null) return root.preOrderSearch(no);
        else return null;
      }
    
      // 中序查找
      public HeroNode midOrderSearch(int no) {
        if (root != null) return root.midOrderSearch(no);
        else return null;
      }
    
      // 后序查找
      public HeroNode postOrderSearch(int no) {
        if (root != null) return root.postOrderSearch(no);
        else return null;
      }
    
      // 删除结点
      public HeroNode deleteNode(int no) {
        HeroNode delNode = null;
        if (root != null) {
            if (root.no == no) {
                delNode = root;
                root = null;
                return delNode;
            } else {
                return root.deleteNode(no);
            }
        } else throw new RuntimeException("二叉树为空");
      }
    
    }
    
    class HeroNode {
        public int no;
        public String name;
        public HeroNode left;
        public HeroNode right;
    
        public HeroNode(int no, String name) {
            this.no = no;
            this.name = name;
        }
    
        // 前序遍历
        public void preOrderBiTree() {
            System.out.println(this);
    
            // 递归 前序遍历左子树
            if(this.left != null)
                this.left.preOrderBiTree();
    
            // 递归 前序遍历右子树
            if(this.right != null)
                this.right.preOrderBiTree();
        }
    
        // 中序遍历
        public void midOrderBiTree() {
            // 递归 中序遍历左子树
            if(this.left != null)
                this.left.midOrderBiTree();
    
            System.out.println(this);
    
            // 递归 中序遍历右子树
            if(this.right != null)
                this.right.midOrderBiTree();
        }
    
        // 后序遍历
        public void postOrderBiTree() {
            // 递归 后序遍历左子树
            if(this.left != null)
                this.left.postOrderBiTree();
    
            // 递归 后序遍历右子树
            if(this.right != null)
                this.right.postOrderBiTree();
    
            System.out.println(this);
        }
    
        /**
        * 前序查找
        * @param no 结点编号
        * @return 找到则返回该结点, 否则返回null
        */
        public HeroNode preOrderSearch(int no) {
            HeroNode node = null;
            // 1. 比较当前结点是不是
            // System.out.printf("[前序] %d → ", this.no);
            if(this.no == no) return this;
    
            // 2. 对左子树递归前序查找
            if(this.left != null)
                node = this.left.preOrderSearch(no);
    
            // 在左边找到, 就没必要再去递归找右边了
            if(node != null) return node;
    
            // 3. 对右子树递归前序查找
            if(this.right != null)
                node = this.right.preOrderSearch(no);
    
            return node;
        }
    
        /**
        * 中序查找
        * @param no 结点编号
        * @return 找到则返回该结点, 否则返回null
        */
        public HeroNode midOrderSearch(int no) {
            HeroNode node = null;
            // 1. 对左子树递归中序查找
            if(this.left != null)
                node = this.left.midOrderSearch(no);
            if(node != null)
                return node;
    
            // 2. 判断
            // System.out.printf("[中序] %d → ", this.no);
            if(this.no == no)
                return this;
    
            // 3. 对右子树递归中序查找
            if(this.right != null)
                node = this.right.midOrderSearch(no);
    
            return node;
        }
    
        /**
        * 后序查找
        * @param no 结点编号
        * @return 找到则返回该结点, 否则返回null
        */
        public HeroNode postOrderSearch(int no) {
            HeroNode node = null;
    
            // 1. 对左子树递归后序查找
            if (this.left != null)
                node = this.left.postOrderSearch(no);
            if (node != null)
                return node;
    
            // 2. 对右子树递归后序查找
            if (this.right != null)
                node = this.right.postOrderSearch(no);
            if (node != null)
                return node;
    
            // 3. 判断
            // System.out.printf("[后序] %d → ", this.no);
            if (this.no == no)
                return this;
    
            return node;
        }
    
        /**
        * 删除结点
        * @param no 待删结点编号
        * @return 返回以no为编号的结点; 如果没找到返回null
        */
        public HeroNode deleteNode(int no) {
            HeroNode delNode = null;
            if (this.left != null && this.left.no == no) {
                delNode = this.left;
                this.left = null;
                return delNode;
            }
    
            if (this.right != null && this.right.no == no) {
                delNode = this.right;
                this.right = null;
                return delNode;
            }
    
            if (this.left != null) {
                delNode = this.left.deleteNode(no);
                if (delNode != null) return delNode;
            }
    
            if (this.right != null)
                delNode = this.right.deleteNode(no);
            return delNode;
        }
    
        @Override
        public String toString() {
            return "[no=" + no + ", name=" + name + "]";
        }
    }
    
  • 相关阅读:
    mac给文件夹添加权限命令,mac设置文件夹权限
    idea自动生成Entity类的get方法和set方法
    mac连接linux服务器远程
    phpstorm中设置文件保存后自动上传FTP
    cmd删除文件夹或删除文件
    SpringBoot封装增删改查接口
    修改 Docker 的默认存储路径
    ES6ES11 20152020
    js开发中可用的位运算
    Git 修改最近一次的提交注释 包括已push和未push
  • 原文地址:https://www.cnblogs.com/liujiaqi1101/p/12327918.html
Copyright © 2020-2023  润新知