算法学习之二叉树

概念

每个节点最多有两个的子节点的树,称为二叉树,二叉树是最基础的树,其他的算法树大多是在二叉树的前提下加以限制,或有特殊要求。

二叉树的相关术语:

  • 节点:包含一个数据元素及若干指向子树分支的信息,一般一个节点所包含的属性有:节点数值,左节点,右节点

  • 节点的度:一个节点拥有子树的数目称为节点的度,即一个节点有几个子分支,没有子节点度为0,仅有一个子节点度为1,以此类推

  • 叶子节点:也称为终端节点,没有子树的节点或者度为零的节点

  • 分支节点:也称为非终端节点,度不为零的节点称为非终端节点

  • 树的度:树中所有节点的度的最大值

  • 节点的层次:从根节点开始,假设根节点为第1层,根节点的子节点为第2层,依此类推,如果某一个节点位于第L层,则其子节点位于第L+1层

  • 树的深度:也称为树的高度,树中所有节点的层次最大值称为树的深度

  • 有序树:如果树中各棵子树的次序是有先后次序,则称该树为有序树

  • 无序树:如果树中各棵子树的次序没有先后次序,则称该树为无序树

  • 森林:由m(m≥0)棵互不相交的树构成一片森林。如果把一棵非空的树的根节点删除,则该树就变成了一片森林,森林中的树由原来根节点的各棵子树构成

二叉树的性质

  • n0 + n2 = n

  • n0 = n2 + 1

  • 2* n2 + 1 = n

  • n2 = (n-1)/2

数字为节点的度

二叉树的创建

在java中创建一个二叉树分为两部分:节点和树

这里直接上代码

/**节点类**/
class TreeNode {
    private int id;
    private String name;
    private TreeNode left;
    private TreeNode right;

    @Override
    public String toString() {
        return "TreeNode{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public TreeNode(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public TreeNode() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }
}

/**树类**/
class BinaryTree{
    private TreeNode root;

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

 有了这两个类,我们只需创建几个节点,将其中一个节点设置为树的根结点,并将其余的节点放在其左右节点即可

public class BinaryTreeDemo {
    public static void main(String[] args) {
        // 先创建二叉树的节点
        BinaryTree binaryTree = new BinaryTree();
        TreeNode root = new TreeNode(1,"嘉然");
        TreeNode node2 = new TreeNode(2,"向晚");
        TreeNode node3 = new TreeNode(3,"乃琳");
        TreeNode node4 = new TreeNode(4,"贝拉");
        TreeNode node5 = new TreeNode(5,"珈乐");

        // 手动创建二叉树
        binaryTree.setRoot(root);
        root.setLeft(node3);
        root.setRight(node2);
        node2.setRight(node4);
        node2.setLeft(node5);
    }
}

此时我们就创建好了一个二叉树,如图

二叉树的遍历

二叉树的遍历有三种:先序遍历,中序遍历,后序遍历

  • 先序遍历

    • 遍历顺序为根、左、右,即先遍历一个树的根结点,在遍历其左子树,最后是右子树,遍历是一个递归的过程,直到遍历到没有左右子节点的叶子节点返回上一层

    • 先序遍历输出上述二叉树的结果为:1、3、2、5、4

  • 中序遍历

    • 遍历顺序为左、根、右,即先遍历一个树的左子树,在遍历其根结点,最后是右子树,遍历是一个递归的过程,直到遍历到没有左右子节点的叶子节点返回上一层

    • 中序遍历输出上述二叉树的结果为:3、1、5、2、4

  • 后序遍历

    • 遍历顺序为左、右、根,即先遍历一个树的左子树,在遍历其右子树,最后是根结点,遍历是一个递归的过程,直到遍历到没有左右子节点的叶子节点返回上一层

    • 中序遍历输出上述二叉树的结果为:3、5、4、2、1

这里给出三种遍历打印和查找的代码

class TreeNode {

    // 先序遍历(根 左 右)
    public void preOrder() {
        System.out.println(this);
        if (this.left != null) {
            this.left.preOrder();
        }
        if (this.right != null) {
            this.right.preOrder();
        }
    }

    // 中序遍历(左 根 右)
    public void infixOrder() {
        if (this.left != null) {
            this.left.infixOrder();
        }
        System.out.println(this);
        if (this.right != null) {
            this.right.infixOrder();
        }
    }

    // 后序遍历(左 右 根)
    public void postOrder() {

        if (this.left != null) {
            this.left.postOrder();
        }
        if (this.right != null) {
            this.right.postOrder();
        }
        System.out.println(this);
    }

    /**
     * 先序查找
     * @param id
     * @return
     */
    public TreeNode preFind(int id) {
        TreeNode treeNode = null;
        if (this.id == id) {
            treeNode = this;
            return treeNode;
        }
        if (this.left != null) {
            treeNode = this.left.preFind(id);
        }
        if (this.right != null) {
            treeNode = this.right.preFind(id);
        }
        return treeNode;
    }

    /**
     * 中序查找
     * @param id
     * @return
     */
    public TreeNode infixFind(int id) {
        TreeNode treeNode = null;
        if (this.left != null) {
            treeNode = this.left.infixFind(id);
        }
        if (this.id == id) {
            treeNode = this;
            return treeNode;
        }
        if (this.right != null) {
            treeNode = this.right.infixFind(id);
        }
        return treeNode;
    }

    /**
     * 后序查找
     * @param id
     * @return
     */
    public TreeNode postFind(int id) {
        TreeNode treeNode = null;
        if (this.left != null) {
            treeNode = this.left.postFind(id);
        }
        if (this.right != null) {
            treeNode = this.right.postFind(id);
        }

        if (this.id == id) {
            treeNode = this;
            return treeNode;
        }
        return treeNode;
    }
}

class BinaryTree{
    /**
     * 先序查找
     * @param id
     * @return
     */
    public TreeNode preFind(int id){
        if (this.root == null){
            System.out.println("二叉树为空");
            return null;
        }else {
            return root.preFind(id);
        }
    }

    /**
     * 中需查找
     * @param id
     * @return
     */
    public TreeNode infixFind(int id){
        if (this.root == null){
            System.out.println("二叉树为空");
            return null;
        }else {
            return root.infixFind(id);
        }
    }

    /**
     * 后序查找
     * @param id
     * @return
     */
    public TreeNode postFind(int id){
        if (this.root == null){
            System.out.println("二叉树为空");
            return null;
        }else {
            return root.postFind(id);
        }
    }

    // 先序遍历
    public void preOrder(){
        if (this.root != null) {
            root.preOrder();
        }else {
            System.out.println("二叉树为空,无法遍历");
        }
    }

    // 中序遍历
    public void infixOrder(){
        if (this.root != null){
            root.infixOrder();
        }else {
            System.out.println("二叉树为空,无法遍历");
        }
    }

    // 后序遍历
    public void postOrder(){
        if (this.root != null){
            root.postOrder();
        }else {
            System.out.println("二叉树为空,无法遍历");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值