树二叉树满二叉树完全二叉树遍历二叉树java实现

Posted 顧棟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树二叉树满二叉树完全二叉树遍历二叉树java实现相关的知识,希望对你有一定的参考价值。

树的定义

树是 n ( N ≥ 0 ) \\mathrm{n(N\\ge0)} n(N0)个结点的有限集。在任意一棵非空树中,

(1)有且仅有一个特定的结点(root),称为根

(2)当 n > 1 \\mathrm{n>1} n>1时,其余结点可以分为 m ( m > 0 ) \\mathrm{m(m>0)} m(m>0) 个互不相交的有限集,每一个集合本身也是一棵树,并且这些有限集称为根的子树。

树的结点相关概念

树的结构是一个递归结构。

树的结点包含一个数据元素及若干指向其子树的分支。

结点拥有的子树的个数称为结点的度(Degree)

度为0的节点称为叶子或者终端结点。

度不为0的结点称为非终端结点或者分支结点

除了根结点之外的分支结点也成为内部结点

树的度是树内各结点的度的最大值。

结点子树的根称为这个结点的孩子

该结点也称为孩子的双亲

同一个双亲的孩子之间互称为兄弟

节点的祖先是从根结点到该结点所经分支上所有的节点。

以某节点为根的子树中的任一结点都称为该结点的子孙

结点的层次,从根开始为第一层,根的孩子为第二层,层次以此类推。

双亲在同一层的节点互为堂兄弟

树中最大的层次为树的深度(depth)或高度

有序树 树中结点的各子树从左至右是有次序的,且不能互换,

无序树 不满足有序数条件就是无序树。

二叉树

二叉树的定义

二叉树是另一种树型结构,每个结点至多有两棵子树,子树有左右之分,次数不可以变。

二叉树的5种形态

  1. 空二叉树
  2. 仅有根结点的二叉树
  3. 右子树为空的二叉树
  4. 左子树为空的二叉树
  5. 左、右子树均非空的二叉树

满二叉树

一棵深度为 k \\mathrm{k} k 且有 2 k − 1 \\mathrm{2^k-1} 2k1的个结点的二叉树,编号方式:从根开始自上而下,自左而右累加编号。

补图

完全二叉树

深度为 k \\mathrm{k} k 的,有 n \\mathrm{n} n 个节点的二叉树,当且仅当其每一个结点都与深度为 k \\mathrm{k} k 的满二叉树中编号从1至 n \\mathrm{n} n的结点意义对应时,称为完全二叉树。

补图

二叉树的性质

  1. 在二叉树的第 i \\mathrm{ i } i 层上最多有 2 i − 1 \\mathrm{ 2^{i-1}} 2i1个结点( i ≥ 1 \\mathrm{i\\geq1} i1)。
  2. 深度为 k \\mathrm{ k } k 的二叉树至多有 2 k − 1 \\mathrm{2^k-1} 2k1个节点( k ≥ 1 \\mathrm{k\\geq1} k1)。
  3. 对任何一颗二叉树 T \\mathrm{ T } T,如果其终端节点数为 n 0 \\mathrm{n_0} n0,度为2的节点数为 n 2 \\mathrm{n_2} n2,则 n 0 = n 2 + 1 \\mathrm{n_0=n_2+1} n0=n2+1

完全二叉树的两个特性

  1. 具有 n \\mathrm{ n } n个节点的完全二叉树的深度为 ⌊ l o g 2 n ⌋ + 1 \\mathrm{\\left \\lfloor log_2 n\\right \\rfloor+1} log2n+1,按层序编号,编号为i的结点的层次在 ∣ l o g 2 i ∣ + 1 \\mathrm{\\left| log_2^i \\right|+1} log2i+1
  2. 一棵深度为 k \\mathrm{ k } k 的完全二叉树至少有 2 k − 1 \\mathrm{2^{k-1}} 2k1的节点,至多 2 k − 1 \\mathrm{2^k-1} 2k1个结点。

二叉树的存储结构

  1. 顺序存储结构

    使用一组地址连续的存储单元依次自上而下、自左而右存储完全二叉树上的结点元素,即将完全二叉树上编号为 i \\mathrm{ i } i 的结点元素存储在如上定义的一维数组下标为 i − 1 \\mathrm{ i-1 } i1 的分量中。这个存储结构仅仅适用完全二叉树,在最坏的情况下,一个深度为 k \\mathrm{ k } k 且只有 k \\mathrm{ k } k 个节点的单支树(树中不存在度为2的结点)。

  2. 链式存储结构

    结点结构的不同,会构成不同的链式存储结构,由二叉树的定义可知,二叉树的结点拥有一个数据域和分别指向左右指针域,这种结构成为二叉链表,为了快速找到结点的双亲,会在结点结构上增加一个双亲指针域,这的结构称为三叉链表。

遍历二叉树

遍历指,每个结点有且仅被访问一次

  1. 先序遍历

    先判断空,若不为空则

    1. 访问根节点;
    2. 先序遍历左子树;
    3. 先序遍历右子树。
  2. 中序遍历

    先判断空,若不为空则

    1. 中序遍历左子树;
    2. 访问根节点;
    3. 中序遍历右子树。
  3. 后序遍历

    先判断空,若不为空则

    1. 后序遍历左子树;
    2. 后序遍历右子树;
    3. 访问根节点。

Java实现

package tree;

public class TreeNode {
    /**
     * 节点上的值
     */
    private int value;
    /**
     * 左节点
     */
    private TreeNode left;
    /**
     * 右节点
     */
    private TreeNode right;

    public TreeNode() {

    }

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

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

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }
}
package tree;

import org.apache.commons.lang.StringUtils;

/**
 * 遍历二叉树
 */
public class TraversalBinaryTree {

    public static final StringBuilder VALUES = new StringBuilder();
    public static final String SEPARATOR = "->";
    public static final int SEPARATOR_LENGTH = SEPARATOR.length();

    /**
     * 先序遍历
     */
    public static String prefaceReadTree(TreeNode tree) {
        String result = "";
        if (null != tree) {
            VALUES.append(tree.getValue()).append(SEPARATOR);
            prefaceReadTree(tree.getLeft());
            prefaceReadTree(tree.getRight());
        }
        if (StringUtils.isNotBlank(VALUES.toString())) {
            result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
        }
        return result;
    }

    /**
     * 中序遍历
     */
    public static String inorderReadTree(TreeNode tree) {
        String result = "";
        if (null != tree) {
            inorderReadTree(tree.getLeft());
            VALUES.append(tree.getValue()).append(SEPARATOR);
            inorderReadTree(tree.getRight());
        }
        if (StringUtils.isNotBlank(VALUES.toString())) {
            result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
        }
        return result;
    }

    /**
     * 后序遍历
     */
    public static String postorderReadTree(TreeNode tree) {
        String result = "";
        if (null != tree) {
            postorderReadTree(tree.getLeft());
            postorderReadTree(tree.getRight());
            VALUES.append(tree.getValue()).append(SEPARATOR);
        }
        if (StringUtils.isNotBlank(VALUES.toString())) {
            result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
        }
        return result;
    }
}
package tree;

public class Client {

    public static void main(String[] args) {
        String result = "";
        TreeNode treeNode = init();

        result = TraversalBinaryTree.prefaceReadTree(treeNode);
        System.out.println("先序结果=" + result);

        TraversalBinaryTree.VALUES.delete(0, result.length() + 2);
        result = TraversalBinaryTree.inorderReadTree(treeNode);
        System.out.println("中序结果=" + result);

        TraversalBinaryTree.VALUES.delete(0, result.length() + 2);
        result = TraversalBinaryTree.postorderReadTree(treeNode);
        System.out.println("后序结果=" + result);
    }

    /**
     * 构建如下的二叉树,同时是个满二叉树
     *       1
     *     /  \\
     *    2    3
     *  /  \\  / \\
     * 4   5 6   7
     */
    public static TreeNode init() {
        TreeNode root = new TreeNode(1);
        TreeNode treeNode2 = new TreeNode(2);
        TreeNode treeNode3 = new TreeNode(3);
        root.setLeft(treeNode2);
        root.setRight(treeNode3);
        TreeNode treeNode4 = new TreeNode(4);
        TreeNode treeNode5 = new TreeNode(5);
        TreeNode treeNode6 = new TreeNode(6);
        TreeNode treeNode7 = new TreeNode(7);
        treeNode2.setLeft(treeNode4);
        treeNode2.setRight(treeNode5);
        treeNode3.setLeft(treeNode6);
        treeNode3.setRight(treeNode7);
        return root;
    }
}
先序结果=1->2->4->5->3->6->7
中序结果=4->2->5->1->6->3->7
后序结果=4->5->2->6->7->3->1

参考

  1. 《数据结构 (C语言版)》 严蔚敏

以上是关于树二叉树满二叉树完全二叉树遍历二叉树java实现的主要内容,如果未能解决你的问题,请参考以下文章

二叉树入门知识——一篇了解二叉树

算法漫游指北(第十三篇):二叉树的基本概念满二叉树完全二叉树二叉树性质二叉搜索树二叉树定义二叉树的广度优先遍历

二叉树满二叉树完全二叉树

二叉树及特殊二叉树(满二叉树完全二叉树二叉排序树平衡二叉树)的定义和性质(附详细推理过程)

Java复习--树

Java复习--树