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

1. 遍历方式

a. 先序遍历 // 先访问根结点

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

b. 中序遍历 // 中间访问根结点

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

c. 后序遍历 // 最后访问根结点

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

2. 查找结点

3. 删除结点

3.1 规定

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

3.2 思路分析

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

  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 + "]";
    }
    
}

猜你喜欢

转载自www.cnblogs.com/liujiaqi1101/p/12327918.html