有且仅有一个特定的称为的结点。当结点数量大于1时,除根结点外其余结点被分割互不相交集合,其中每个集合又是一棵数,并称为这个结点的子树。


个人理解:

怎么理解这段话的意思?就是说当有n个结点的时候,首先n个结点是个集合,但需要存在根结点p。该结点会将数字分割成2个集合,如果要满足树的定义,则这2个集合互不相交。(此时只是根结点分割后能满足树的定义)。分割成{a1,a2}集合后a1集合又可以按照根结点一样在分割(其a1集合又必须满足树的定义)。而a1称为根结点p的子树


:树从根节点往下,层依次为1,2,3….。
:该节点下面的直接子树个数总和。
叶子结点(终端结点):度为0的结点。
分支结点(非终端结点):度不为0的结点,很明显就是跟。


不多bb,下面直接具体说二叉树的实现

如果我们的二叉树是这样一棵树。要实现数据结构的存储该咋办呢?

java 将树的每一个结点递归_二叉树

首先了解下“扩展二叉树”的定义

扩展二叉树:二叉树的每个结点的空指针都引出一个虚节点,其值为特定值,如使用“#”表示其为空。

更具扩展二叉树的规则,则有如下树结构

java 将树的每一个结点递归_前序遍历_02


前序遍历顺序为:a->#->b->c->#->#->#。

想想为什么使用扩展二叉树呢?

  • 扩展二叉树通过前序遍历的顺序可以直接确定树的结构,不在需要中序遍历顺序。

二叉树的构造具体实现

使用链表结构存储结点,以及结点关系
public class Test {

    public static void main(String[] args) throws Exception {
        //必须是扩展二叉树的格式的前序遍历
        TwoXTree tree=new TwoXTree(new Object[]{"a",'#',"b",'c','#','#','#'});
        TwoXTreeNode node= tree.getTree();
        System.out.println(node);
    }
}
/**
 * 二叉树结点
 * <p>(二叉树结点和孩子兄弟表示法不同,孩子兄弟表示法中的结点使用的是前驱表示第一个孩子结点。后继表示该孩子结点的兄弟,并且树不存在左右之分,左右之分是针对2x树)
 * @author name:zf Email:623039066@qq.com
 */
class TwoXTreeNode{
    private TwoXTreeNode left;
    private TwoXTreeNode right;
    private Object data;
    public TwoXTreeNode getLeft() {
        return left;
    }
    public void setLeft(TwoXTreeNode left) {
        this.left = left;
    }
    public TwoXTreeNode getRight() {
        return right;
    }
    public void setRight(TwoXTreeNode right) {
        this.right = right;
    }
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
}

class TwoXTree{
    private TwoXTreeNode twoXTree;
    private int index;
    /**
     * 构造二叉树
     * @param preOrder 遵循扩展二叉树的前序遍历二叉树顺序的数据数组
     * @throws Exception 
     */
    public TwoXTree(Object[] preOrder) throws Exception {
        super();
        if(preOrder==null || preOrder.length==0){
            throw new Exception("前序遍历顺序不正确,请重新检查。");
        }
        index=0;
        this.twoXTree=init(preOrder);
    }

    private TwoXTreeNode init(Object[] preOrder){
        Object o= preOrder[index++];
        if(o instanceof Character && (char)o=='#'){
            return null;
        }else{
            TwoXTreeNode node=new TwoXTreeNode();
            node.setData(o);
            node.setLeft(init(preOrder));
            node.setRight(init(preOrder));
            return node;
        }
    }

    public TwoXTreeNode getTree(){
        return this.twoXTree;
    }
}

通过debug模式即可看到树结构的正确性。


多维数组的存储

java 将树的每一个结点递归_java 将树的每一个结点递归_03

/**
 * 演示多维数组存储
 * @author name:zf Email:623039066@qq.com
 */
class ManyDimensionArray{
    private Object [] manyDimensionArray;
    private int p;
    private int[] dimension;

    //使用new ManyDimensionArray(2,5) 及等价于new object[2][5];
    public ManyDimensionArray(int... dimension) {
        super();
        int length=1,q=0;
        this.dimension=new int[dimension.length];
        for(int i : dimension){
            this.dimension[q++]=i;
            length=length*i;
        }
        manyDimensionArray=new Object[length];
        p=0;
    }

    public void init(Object ... objects){
        for(Object o : objects){
            manyDimensionArray[p++]=o;
        }
    }

    public Object[] getArray(){
        return this.manyDimensionArray;
    }
}