06.Java数据结构与算法之~二叉树的基本概念及遍历

06.Java数据结构与算法之~二叉树

       树(Tree)是n(n >= 0)个结点的有限集。n = 0时称为空树。

       在任意一颗非空树中,有且仅有一个特定的称为根(Root)的结点。

       其余结点可分为m(m > 0)个互不相交的有限集 T1、T2、、、Tm,其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)

以下不是树

原因: E既是D的子集又是C的子集,违反了树的概念!

结点的度

       结点拥有的子树数称为结点的度。度为0的结点称为叶子结点或终端结点。度不为0的结点称为非终端结点或分支结点。除根结点以外,分支结点也称为内部结点。树的度是树内各结点的度的最大值。

层次与深度

       结点的层次(Level)从根开始定义起,根为第一层,根的孩子为第二层。若某结点在第1层,则其子树的根就在 i + 1 层。其双亲在同一层的结点互为堂兄弟。显然图中的D、E、F是堂兄弟,而G、H、I、J也是。树中结点的最大层次称为树的深度(Deph)或高度,当前树的深度为4。

有序与无序树

       如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称无序树。

二叉树

为什么需要树这种数据结构?

数组存储方式的分析:

       优点:通过下标方式访问元素,速度快。对于有序数组,还可以用二分查找提高检索速度

       缺点:如果要检索某个具体值,或者插入删除值会整体移动,效率较低

链式存储方式的分析:

       优点:在一定程度上对数组存储方式有优化,比如,插入一个数值结点只需要将插入结点连接到链表中即可,删除也只需要将前一个结点指向后一个结点不需要整体移动,因此效率好

       缺点:在进行检索时,效率依然很低。因为需要从头遍历

树存储方式分析:

       比如二叉排序树(Binary sort tree)既可以保证数据的检索速度,又可以保证插入、删除、修改的速度

什么是二叉树?

       每个节点最多只能有两个子节点的一种形式称为二叉树

       二叉树的子节点分为左节点和右节点

斜树

       所有节点都只有左子树的二叉树称为左斜树,只有右子树的二叉树称为右斜树。总之统称为斜树

满二叉树

       在一颗二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。

二叉树遍历代码实现

定义Tree接口

public interface Tree {
    //构建树
    void CreateBinaryTree(Object tree, Object left, Object right);
    //先序遍历
    void PreOrder();
    //中序遍历
    void InfixOrder();
    //后序遍历
    void PostOrder();
}

编写BinaryTree二叉树实现类

public class BinaryTree implements Tree{
    private BinaryTree left;    //左子树
    private BinaryTree right;   //右子树
    private Object root;        //根节点

    //-------构造传值-------
    public BinaryTree(Object data){
        root =  data;
    }
    @Override
    //-------构建树-------         为了兼容接口统一Object
    public void CreateBinaryTree(Object tree, Object left, Object right){
        //强制转换
        BinaryTree Tree = (BinaryTree) tree;
        Tree.left = (BinaryTree)left;
        Tree.right = (BinaryTree)right;
    }

    //-------先序遍历-------
    @Override
    public void PreOrder() {
        //判断二叉树是否为空
        if(root != null){
            System.out.print(root + " ");
            //判断左子节点是否为空
            if(left != null){
                left.PreOrder();
            }
            if(right != null){
                right.PreOrder();
            }
        }else{
            //说明树为空,空指针异常
            throw new NullPointerException();
        }
    }
    //-------中序遍历-------
    @Override
    public void InfixOrder() {
        //判断二叉树是否为空
        if(root != null){
            //判断左子节点是否为空
            if(left != null){
                left.InfixOrder();
            }
            System.out.print(root + " ");
            if(right != null){
                right.InfixOrder();
            }
        }else{
            //说明树为空,空指针异常
            throw new NullPointerException();
        }
    }
    //-------后序遍历-------
    @Override
    public void PostOrder() {
        //判断二叉树是否为空
        if(root != null){
            //判断左子节点是否为空
            if(left != null){
                left.PostOrder();
            }
            if(right != null){
                right.PostOrder();
            }
            System.out.print(root + " ");
        }else{
            //说明树为空,空指针异常
            throw new NullPointerException();
        }
    }
}

测试:

    public static void main(String[] args) {
        Tree A = new BinaryTree("A");
        Tree B = new BinaryTree("B");
        Tree C = new BinaryTree("C");
        Tree D = new BinaryTree("D");
        Tree E = new BinaryTree("E");
        Tree F = new BinaryTree("F");
        Tree G = new BinaryTree("G");

        A.CreateBinaryTree(A,B,C);  //定义A的两个子节点
        A.CreateBinaryTree(B,D,E);  //定义B的两个子节点
        A.CreateBinaryTree(C,F,G);  //定义C的两个子节点

        System.out.println("先序遍历");
        A.PreOrder();
        System.out.println("\n中序遍历");
        A.InfixOrder();
        System.out.println("\n后序遍历");
        A.PostOrder();      
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章