Loading

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 + "]";
    }
}
posted @ 2020-02-18 20:50  tree6x7  阅读(139)  评论(0编辑  收藏  举报