探秘二叉深林——浅解二叉树

最近我又学习了一种数据结构。

这种数据结构还挺有趣的,名叫二叉树。

在了解二叉树之前,我们得先了解这个叫树的数据结构。

树:一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看 起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

具有以下特点:

1.有一个特殊的结点,称为根结点,根结点没有前驱结点。

2.除根结点外,其余结点被分成M(M > 0)个互不相交的集合T1、T2、......、Tm,其中每一个集合Ti (1 <= i <= m) 又是一棵与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继。

3.树是递归定义的。

注意:树形结构中,子树之间不能有交集,否则就不是数据结构。

如图所示:

那么我们看完这个图后,我们还得了解一些其他东西:

结点的度:一个结点含有子树的个数称为该结点的度; 如上图:A的度为4.

树的度:一棵树中,所有结点度的最大值称为树的度; 如上图:树的度为4.

叶子节点或终端节点:度为0的节点称为叶子节点,如上图:B、F、G等

双亲节点或者父节点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点。

孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点。

根结点:一棵树中,没有双亲结点的结点;如上图:A

结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推。

树的高度或深度:树中结点的最大层次; 如上图:树的高度为3.

后续还有一些其他概念比如:非终端结点或分支结点、兄弟结点、堂兄弟结点、结点的祖先、子孙、森林.

那么树的一些基本概念了解清楚了.

我们就要表示一颗树出来了,那么我们表示方式也有很多,比如:双亲表示法、孩子表示法、孩子双亲表示法、孩子兄弟表示法。

我们常见且较为简单的就是孩子兄弟表示法。

接下来我们就讲解下我们本章的重点:

二叉树。

概念:一棵二叉树是结点的一个有限集合,

该集合: 1. 或者为空 2. 或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。

从上图可以看出:

1. 二叉树不存在度大于2的结点

2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树。

注意:只有一个根节点也是二叉树,只有右子树或者左子树也叫二叉树。

二叉树中我们要学习其一种特殊形态——完全二叉树

完全二叉树就是以上提供的图片中,少了个7节点,

而上面的图片是一个满二叉树,满二叉树是一种特殊的完全二叉树。

ok,接下来我们一起认识下二叉树一些性质:
1。若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有(i>0)个结点

2.若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点数是 (k>=0)

3.对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1。

4.. 具有n个结点的完全二叉树的深度k为 上取整。

5.对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i 的结点有:

                                     a: 若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点

                                     b:若2i+1<n,左孩子序号:2i+1,否则无左孩子

                                     c:若2i+2,右孩子序号:2i+2,否则无右孩子。

在我们了解完基础的一些东西后,我们就可以试着把二叉树以及一些基本功能实现出来。

那我们首先得把这个二叉树实现出来:

public class Binary_Tree {
    static class TreeNode {
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }

    //二叉树的创建,现以最简单的形式创建
    public TreeNode createTree() {
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        return A;
    }
}

这里的创建就以非常简单的形式去创建。

我们实现的第一个功能就是遍历,因为这个功能是相对简单的。

遍历

这里有分为前序遍历、中序遍历、后序遍历。

前序遍历(先序遍历):根节点->根的左子树->根的右子树

中序遍历:根的左子树->根节点->根的右子树

后序遍历:根的左子树->根的右子树->根节点

注意:我们这里实现的遍历是以递归去实现的。

以前序遍历举个例子:

代码实现:

前序遍历

public void preorder(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.print(root.val + " ");
        preorder(root.left);
        preorder(root.right);
    }

我们先打印根节点,再去走左子树,走完左子树,再走右子树。

中序遍历

 public void inorder(TreeNode root) {
        if (root == null) {
            return;
        }
        inorder(root.left);
        System.out.print(root.val + " ");
        inorder(root.right);
    }

后续遍历

 public void postorder(TreeNode root) {
        if (root == null) {
            return;
        }
        postorder(root.left);
        postorder(root.right);
        System.out.print(root.val + " ");
    }

遍历这个功能写完后,接着写个求树的多少个节点的方法。

树的节点数量:

public int size(TreeNode root) {
        if (root == null) {
            return 0;
        }
        //思路:左树的节点+右树的节点+1=整棵树的节点
        int ret = size(root.left) + size(root.right) + 1;
        return ret;
    }

获取树的节点的数量,我们看之前提供的二叉树的图片,发现左子树的节点+右子树的jied+1(根节点)=其数量

所以我们可以递归去实现它。走完左边再走右边。

接下来我们实现下,求叶子节点的个数。

求叶子节点个数:

前面我们说,叶子节点指的是左右孩子是没有的。

那么同时我们也可以根据给出的二叉树的图得出:叶子节点等于=左孩子的叶子节点+右孩子的叶子节点。

public int leafNode(TreeNode root) {
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 1;
        }
        return leafNode(root.left) + leafNode(root.right);
    }

下一个功能是求树的高度。

书的高度

那么我们树的高度怎么求呢?

我们细看给出的二叉树的图:

树的高度可以这样子求,左子树右子树的最大值+1。

我们可以看上面的图,左子树和右子树都是2,那么左子树大于右子树吗?

都是2,不大于,所以让右子树的高度+1。

public int getHeight(TreeNode root) {
        //思路:左子树右子树最大值+1.
        if (root == null) {
            return 0;
        }
        int left = getHeight(root.left);
        int right = getHeight(root.right);
        return left > right ? left + 1 : right + 1;
    }

我们先获取下左子树的高度和右子树的高度,然后在return语句进行比较。

最后我们来实现最后一个方法

叫做find方法

这个方法是找出是否里面存在某个节点的值

find:

这个方法思路:

首先找根节点,找不到去根节点的左子树去找,找到了,就返回,左子树找不到就去右子树去找,同样,找到就返回

public TreeNode find(TreeNode root, char val) {
        if (root == null) {
            return null;
        }
        if (root.val == val) {
            return root;
        }
        TreeNode ret = find(root.left, val);
        if (ret != null) {
            return ret;
        }
        ret = find(root.right, val);
        if (ret != null) {
            return ret;
        }
        return null;
    }

ok,我们二叉树简单实现和方法就大概讲到了这里。。

完!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值