树的学习Part1(Java实现)

树的基础和使用二叉树把后缀表达式转为中缀树


4.1 基础知识

4.1.1 树的定义

按照递归的方式定义树。一棵树是一些节点的集合。这些集合可以是空集。如果不是空集,则树由称为根() 的节点r以及0个或者多个非空的(子)树T1,T2,T3,…Tk组成,这些子树中每一棵的根都来自于根r的一条有向的所连接。

每一棵子树的根叫做根r的儿子(child),而r是每一棵子树的根的父亲(parent)

一棵树是N个节点和N-1条边的集合,其中的一个节点叫做根(除了根节点之外每个节点都有且仅有一个父亲,也即是有且仅有一条边),每个节点可以有任意多个儿子,没有儿子的节点称为树叶(leaf),具有相同父亲的节点称为兄弟(siblings),类似还有祖父孙子关系

从节点n1-nk的路径(path) 定义为节点n1 n2 n3 … nk 的一个序列,使得对于1<=i<k节点ni是ni+1的父亲,这条路径的长是为该路径上的边的条数,即k-1,每个节点到自己都有一条长为0的路径,在一棵树中从根到每个节点恰好存在一条路径。

对于任意节点ni,ni的 深度(depth) 为从根到ni的唯一路径的长。因此根的深度为0。ni的高(height) 是从ni到一片树叶的最长路径的长,因此,所有树叶的高都为0.一棵树的高等于他根的高,一棵树的深度等于他最深的树叶的深度;该深度总是等于这棵树的高。如果存在n1到n2的一条路径,那么n1是n2的一位祖先 (ancestor)
。如果n1!=n2,那么n1是n2的真祖先,n2是n1的真后裔(proper descendant)

    /*树的表示*/
    private class TreeNode{
        public Object object;
        public TreeNode firstNode;
        public TreeNode nextSibling;
        public TreeNode() {
        }
    }

4.1.2 树的遍历

三种遍历策略

  • 先序遍历:先对节点的处理再对节点儿子处理

  • 后序遍历:先对节点儿子处理再处理节点

  • 中序遍历:左儿子-节点-右儿子方式,适用于二叉树

三种方式对应着前缀表达式,中缀表达式和后缀表达式

4.2 二叉树

二叉树(binary tree)是一棵树,其中每个节点都不能有多于两个的儿子,二叉树的一个性质是一棵二叉树的平均深度要比节点数N小得多,二叉树的平均深度是O(N^0.5),对二叉查找树(binary search tree),其深度的平均值是O(log(N))

4.2.1 二叉树的实现

    class BinaryNode{
        Object element;
        BinaryNode left;
        BinaryNode right;
    }

4.2.2 后缀表达式转为表达式树(中缀)

思路:我们一个一个的把符号读入表达式,如果符号是运算符,那么弹出两个操作数,创建一个新的Tree,然后再压栈,否则,直接把操作数放到栈里面

    class BinaryNode<T>{
        T element;
        BinaryNode left;
        BinaryNode right;
    }

    @Test
    public void test(){
        String postFixString="ab+cde+**";
        buildInfixTree(postFixString);
    }

    public BinaryNode<String> buildInfixTree(String postFixString){
        BinaryNode<String> root=new BinaryNode<>();
        Stack<BinaryNode<String>> stack=new Stack<>();
        for(int i=0;i<postFixString.length();i++){
            String c=String.valueOf(postFixString.charAt(i));
            if(check(c)){//检测到运算符,弹出两个操作数
                BinaryNode<String> node1=new BinaryNode<>();//例如压入ab,那么弹出ba,node1是b,node2是a
                BinaryNode<String> node2=new BinaryNode<>();
                node1=stack.pop();
                node2=stack.pop();
                BinaryNode<String> sNode=new BinaryNode<>();
                sNode.element=c;
                sNode.left=node2;
                sNode.right=node1;
                stack.push(sNode);
            }else {
                BinaryNode<String> node=new BinaryNode<>();
                node.element=c;
                stack.push(node);
            }

        }
        return stack.peek();
    }

    /**
     * 检查是不是运算符
     * @param c
     * @return
     */
    public boolean check(String c){
        if(c.equals("+")||c.equals("-")||c.equals("*")||c.equals("/")){
            return true;
        }
        return false;
    }
发布了28 篇原创文章 · 获赞 9 · 访问量 2429

猜你喜欢

转载自blog.csdn.net/qq_23594799/article/details/102568138