二叉树的遍历

树(tree)是n个结点的有限集。n=0时表示树为空树。在任意一棵非空树中,有且只有一个结点为根结点(root),当n>1时,其余结点可以分为许多个互不相交的有限集T1、T2···,其中每一个集合本身也是一棵树,并且成为根结点的子树。

如果把上述中的很多集合换为两个集合,就成了树中一种实用价值比较高的树,成为二叉树。这样二叉树最多有两棵子树,分别是左子树和右子树。下面简单说下二叉树的一些规律:

性质一:在二叉树的第i层上至多有2的i-1次方个结点;
性质二:深度为k的二叉树至多有2的k次方减1个结点;
性质三:对于任意一棵二叉树,其叶子结点数为n0,度为2的结点数为n2,度为1的结点数为n1,则有n0=n2+1;
性质四:就有n个结点的完全二叉树的深度为对log2(n)取下限+1;
性质五:对有n个结点的完全二叉树按层序排序,则有:(1)i=1,根结点,无双亲;i>1,根节点为对i/2取下限。(2)如果存在,则i结点的左孩子为2i,右孩子为2i+1。

二叉树的遍历方法一般有四种:前序遍历、中序遍历、后序遍历、层序遍历。前三种是根据根结点在左结点和右结点之间的位置决定的,“根左右”就是前序遍历,“左根右”就是中序遍历,“左右根”就是后序遍历。而层序遍历字如其义,就是简单的从上到下,从左到右的依次遍历。层序遍历用的较少,此处不做研究。但是我们应该清楚前三种遍历方法的实现及根据前序(后序)和中序重新构建树,或者得到后序(前序)遍历的结果,下面就以上几个问题作如下实现。

结点结构:

class TreeNode {
    int value;
    TreeNode left;
    TreeNode right;

    public TreeNode(int value) {
        this.value = value;
    }

    public TreeNode(int value, TreeNode left, TreeNode right) {
        this(value);
        this.left = left;
        this.right = right;
    }
}

前序遍历:

public void prePrint(TreeNode root) {
    if (root != null) {
            System.out.print(root.value + " ");
            prePrint(root.left);
            prePrint(root.right);
    }
}

中序遍历:

public void midPrint(TreeNode root) {
        if (root != null) {
            midPrint(root.left);
            System.out.print(root.value + " ");
            midPrint(root.right);
        }
}

后序遍历:

public void backPrint(TreeNode root) {
        if (root != null) {
            backPrint(root.left);
            backPrint(root.right);
            System.out.print(root.value + " ");
        }
}

由前序、中序重建二叉树:

public TreeNode treeConstruct(int[] pre, int[] mid) {
    if (pre == null || mid == null || pre.length == 0 || mid.length == 0)
        return null;
    else
        return treeCons(pre, mid, 0, pre.length - 1, 0, mid.length - 1);
 }

 private TreeNode treeCons(int[] pre, int[] mid, int preStart, int preEnd,
    int midStart, int midEnd) {
    int rootValue = pre[preStart];
    TreeNode root = new TreeNode(rootValue);
    if (preStart == preEnd) {
        if (midStart == midEnd && pre[preStart] == mid[midEnd])
            return root;
        else
            throw new IllegalArgumentException(
                    "pre[] and mid[] can't match");
    }
    int rootIndex = midStart;
    while (rootIndex <= midEnd && mid[rootIndex] != rootValue) {
        rootIndex++;
    }
    if (rootIndex == midEnd && mid[rootIndex] != rootValue)
        throw new IllegalArgumentException();
    int offset = rootIndex - midStart;
    int preLeftRight = preStart + offset;
    if (offset > 0)
        root.left = treeCons(pre, mid, preStart + 1, preLeftRight,
                midStart, rootIndex - 1);
    if (preLeftRight < preEnd - preStart)
        root.right = treeCons(pre, mid, preLeftRight + 1, preEnd,
                rootIndex + 1, midEnd);
    return root;
 }

转载于:https://www.cnblogs.com/torresliang/p/4827109.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值