15.树基本概念和常用术语

树Tree

树是一种数据结构,它由n(n>0)个有限节点组成具有层次结构关系的集合,像一颗倒挂的树,根向上,叶子向下。

二叉树

二叉树是一同特殊的树,二叉树中每一个节点最多只有2个节点。

  • 二叉树层次从2层开始,在第i层最多有2^(i-1)个节点 如第二层最多2个节点 第三层最多4个节点

  • 高度为k的二叉树 一共最多有2^k-1个节点

  • 完美二叉树:又称满二叉树 最后一层的叶子界面是满的,就是满二叉树,满二叉树节点总数为 2^k - 1 k为层数

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OU2Btjmv-1595558433048)(C:\Users\denglw\AppData\Roaming\Typora\typora-user-images\image-20200723115332526.png)]

  • 完全二叉树:所有叶子节点都在最后一层或者倒数第二层,如果在最后一层要求节点在左边连续,如果在倒数第二层要求节点在右边连续.

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zxkpIS9m-1595558433051)(C:\Users\denglw\AppData\Roaming\Typora\typora-user-images\image-20200723115620493.png)]

  • 完满二叉树: 除了叶子节点所有节点都有2个子节点

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rqBzDylt-1595558433054)(C:\Users\denglw\AppData\Roaming\Typora\typora-user-images\image-20200723115724980.png)]

常用术语:

  • 节点 树上一个存储数据的单元
  • 根节点 最顶层的节点
  • 父节点 节点上连接的上一层节点
  • 子节点 节点向下连接的节点
  • 叶子节点 最后一层的节点 即没有子节点的节点
  • 节点权 节点值
  • 路径 从根节点出发到节点所经过的路线
  • 层 节点在从根节点开始往下数 在第几层
  • 高度 整棵树一共有多少层
  • 子树 一个节点即他的子节点组成一个子树
  • 森林 多颗子树组成森林

遍历说明

在这里插入图片描述

​ 主要看父节点在什么时候输出

  • 前序遍历 先输出父节点 再输出左子树 再输出右子树 1 2 4 5 3 6 7
  • 中序遍历 先输出左子树 再输入父节点 再输出 右子树 4 2 5 1 6 3 7
  • 后续遍历 先输出左子树 再输出右子树 再输出父节点 4 5 2 6 7 3 1
代码示例
  • 删除思路
    1. 判断根节点是不是为空,不为空根节点是不是目标节点
    2. 因为目前的tree是一个单向的所以需要找他的子节点
    3. 如果是左子节点为目标节点 this.left = null 右子节点为目标节点 this.right=null
    4. 如果当前节点的左子节点不是目标节点且左子节点不为空 递归删除
    5. 当前节点左字节递归完毕之后,开始同样的方法递归右子树
public class BinaryTreeDemo {
    /**
     * 节点示意图
     *    1
     * /     \
     * 2      3
     * /     \
     * 5      4
     * 前序 1 2 3 5 4
     * 中序 2 1 5 3 4
     * 后序 2 5 4 3 1
     */
    public static void main(String[] args) {
        Node node1 = new Node(1, "员工1");
        Node node2 = new Node(2, "员工2");
        Node node3 = new Node(3, "员工3");
        Node node4 = new Node(4, "员工4");
        Node node5 = new Node(5, "员工5");
        Node node6 = new Node(5, "员工6");
        BinaryTree tree = new BinaryTree(node1);
        node1.left = node2;
        node1.right = node3;
        node3.left = node5;
        node3.right = node4;
//        node5.right = node6;

//        tree.preOrderTraversal();//12354
//        System.out.println();
//        tree.inOrderTraversal();//21534
//        System.out.println();
//        tree.postOrderTraversal();//25431
//        System.out.println();

//        System.out.println(tree.preOrderFind(5)); // 1 2 3 5 一共4次查找
//        System.out.println(tree.inOrderFind(5)); // 2 1 5 一共3次
//        System.out.println(tree.postOrderFind(5)); // 2 5 一共2次
        tree.del2(3);
        tree.preOrderTraversal();
    }
}


class BinaryTree {
    Node root;

    public BinaryTree(Node root) {
        this.root = root;
    }

    //删除
    public void del2(int id) {
        if (root == null) {
            System.out.println("tree is empty!");
        } else {
            if (root.id == id) {
                root = null;
            } else {
                root.del2(id);
            }
        }
    }

    //删除
    public void del(int id) {
        if (root == null) {
            System.out.println("tree is empty!");
        } else {
            if (root.id == id) {
                root = null;
            } else {
                root.del(id);
            }
        }
    }

    // 前序遍历
    public void preOrderTraversal() {
        if (root == null) {
            System.out.println("tree is empty!");
        } else {
            root.preOrderTraversal();
        }
    }

    // 中序遍历
    public void inOrderTraversal() {
        if (root == null) {
            System.out.println("tree is empty!");
        } else {
            root.inOrderTraversal();
        }
    }

    // 后序遍历
    public void postOrderTraversal() {
        if (root == null) {
            System.out.println("tree is empty!");
        } else {
            root.postOrderTraversal();
        }
    }

    // 前序查找
    public Node preOrderFind(int no) {
        if (root == null) {
            System.out.println("tree is empty!");
            return null;
        } else {
            return root.preOrderFind(no);
        }
    }

    public Node inOrderFind(int no) {
        if (root == null) {
            System.out.println("tree is empty!");
            return null;
        } else {
            return root.inOrderFind(no);
        }
    }

    public Node postOrderFind(int no) {
        if (root == null) {
            System.out.println("tree is empty!");
            return null;
        } else {
            return root.postOrderFind(no);
        }
    }
}

class Node {
    Node left;
    Node right;
    int id;
    Object data;

    public Node(int id, Object data) {
        this.data = data;
        this.id = id;
    }

    @Override
    public String toString() {
        return "Node{" +
                "id=" + id +
                ", data=" + data +
                '}';
    }


    /**
     * 前序遍历 先输出中间节点 再输出左节点 再出输出又节点
     */
    public void preOrderTraversal() {
        System.out.print(this + "\t");
        if (this.left != null) {
            this.left.preOrderTraversal();
        }
        if (this.right != null) {
            this.right.preOrderTraversal();
        }
    }

    /**
     * 中序遍历  先左 再中 后右
     */
    public void inOrderTraversal() {
        if (this.left != null) {
            this.left.inOrderTraversal();
        }
        System.out.print(this + "\t");
        if (this.right != null) {
            this.right.inOrderTraversal();
        }
    }

    /**
     * 后续遍历  左 -> 右 -> 中
     */
    public void postOrderTraversal() {
        if (this.left != null) {
            this.left.postOrderTraversal();
        }
        if (this.right != null) {
            this.right.postOrderTraversal();
        }
        System.out.print(this + "\t");
    }

    /**
     * 前序遍历查找
     *
     * @param id
     */
    public Node preOrderFind(int id) {
        if (this.id == id) {
            return this;
        }
        Node temp = null;
        if (this.left != null) {
            temp = this.left.preOrderFind(id);
        }
        // 左递归没找到尝试右递归
        if (temp == null) {
            if (this.right != null) {
                temp = this.right.preOrderFind(id);
            }
        }
        return temp;
    }

    // 中序查找
    public Node inOrderFind(int id) {
        Node temp = null;
        if (this.left != null) {
            temp = this.left.inOrderFind(id);
        }
        if (temp == null) {
            if (this.id == id) {
                return this;
            }
            if (this.right != null) {
                temp = this.right.inOrderFind(id);
            }
        }
        return temp;
    }

    /**
     * 后序遍历查找
     *
     * @param id
     * @return
     */
    public Node postOrderFind(int id) {
        Node temp = null;
        if (this.left != null) {
            temp = this.left.postOrderFind(id);
        }
        if (temp == null) {
            if (this.right != null) {
                temp = this.right.postOrderFind(id);
            }
        }
        if (temp == null) {
            return this.id == id ? this : null;
        }
        return temp;
    }

    /**
     * 如果是叶子节点直接删除 ,如果不是叶子直接 规定 如果有左子树 将左子树提上来 没有左子树提右子树
     *
     * @param id
     */
    public void del2(int id) {
        // 叶子节点直接删除
        if (this.left != null && this.left.id == id && this.left.left == null && this.left.right == null) {
            this.left = null;
            return;
        }
        if (this.right != null && this.right.id == id && this.right.left == null && this.right.right == null) {
            this.right = null;
            return;
        }

        // 左边非叶子节点 左子树不为空
        if (this.left != null && this.left.id == id && this.left.left != null) {
            this.left = this.left.left;
            return;
        }

        // 左边非叶子节点 左子树为空 右子树不为空
        if (this.left != null && this.left.id == id && this.left.left == null && this.left.right != null) {
            this.left = this.left.right;
            return;
        }

        // 右边非叶子节点 左子树不为空
        if (this.right != null && this.right.id == id && this.right.left != null) {
            this.right = this.right.left;
            return;
        }


        // 右边非叶子节点 左子树为空 右子树不为空
        if (this.right != null && this.right.id == id && this.right.left == null && this.right.right != null) {
            this.right = this.right.right;
            return;
        }

        // 往左递归
        if (this.left != null) {
            this.left.del2(id);
        }

        // 往右边递归
        if (this.right != null) {
            this.right.del2(id);
        }


    }

    /**
     * 最简单的删除,不管是不是叶子节点直接删除 如果是叶子节点删除 如果是不是叶子节点直接删除子树
     *
     * @param id
     */
    public void del(int id) {
        if (this.left != null && this.left.id == id) {
            this.left = null;
            return;
        }

        if (this.right != null && this.right.id == id) {
            this.right = null;
            return;
        }

        // 左节点递归删除
        if (this.left != null) {
            this.left.del(id);
        }

        // 右节点递归删除
        if (this.right != null) {
            this.right.del(id);
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值