数据结构之树(Tree)(二)_二叉树的创建及遍历概述

树的第一部分(数据结构之树(Tree)(一)_树的基础)介绍了树的各个基础:什么是树、树的特点、树的表示方法、树的种类、树在存储结构中的表示、树/森林/二叉树之间的转换(原理)等。

这部分主要介绍下二叉树的创建及遍历(一种实现,主要了解二叉树遍历的过程)。遍历是二叉树重要的运算,是其他运算的基础。树、森林都可以转换成二叉树进行运算。

由于树的内容比较多,实现多样。关于二叉树的多种创建实现、二叉树的多种遍历(非递归、广度优先、深度优先等)实现、树转二叉树的实现 等后续整理总结。

二叉树遍历概述

根据二叉树的根结点及左、右子树遍历的次序,二叉树的遍历主要有3种方式。

  1. 先序遍历
    先遍历根结点,再遍历左子树,最后遍历右子树。
  2. 中序遍历
    先遍历左子树,再遍历根结点,最后遍历右子树。
  3. 后序遍历
    先遍历左子树,再遍历右子树,最后遍历根结点。

数据结构之树(Tree)(二)_二叉树的创建及遍历概述

如图,是一颗二叉树。遍历都是递归的方式。

先序遍历:ABDGHCEFI
中序遍历:BGDHAECIF
后序遍历:GHDBEIFCA

二叉树遍历的一种实现

二叉树先序遍历 创建树

上图看到的图像表示,人看了很容易理解。但在程序中需要通过一定规则实现它,这就需要创建树。(根据输入或者要求,创建实现方法多样,这里采用一种,多种创建方法后续总结。)

单个遍历结果(先序或者中序或者后序)无法确定一棵树的唯一样子。主要是单种遍历方式结果,你无法知道某个结点是否有孩子结点 还是仅有某个孩子结点,所以如果用#表示结点孩子结点不存在的位置,即某结点某方向在此停止,这样树的结构就确定了。然后通过这样的结果来创建树

这样上图,先序遍历的结果就是:AB#DG##H##CE##FI###
注意:每个结点如果孩子结点不存在都要用#表示,即使是叶子结点也需要。

实现参考下面代码中的方法:createBinaryTree()。

创建及遍历的实现

具体看代码和注释,很容易理解:

public class BinaryTree {

    //二叉树结点定义:数据、左孩子、右孩子。
    static class BinaryNode {
        Object data;
        BinaryNode leftChild, rightChild;
		
        public BinaryNode(Object data) {
            this.data = data;
            this.leftChild = this.rightChild = null;
        }
    }
	
    //根结点
    static BinaryNode root;
	
    public BinaryTree() {
        root = null;
    }
	
    //用于先序遍历创建树的输入
    static char[] treeNodes = "AB#DG##H##CE##FI###".toCharArray();
    static int index = -1;
	
    //创建二叉树
    public static BinaryNode createBinaryTree() throws Exception {
        BinaryNode newBinaryNode = null;
        index++;
        if (treeNodes[index] != ‘#‘) {
            newBinaryNode = new BinaryNode(treeNodes[index]);
            newBinaryNode.leftChild = createBinaryTree();
            newBinaryNode.rightChild = createBinaryTree();
        }
        //当碰到# 即newBinaryNode为null,即父结点没有某个孩子结点(左孩子或右孩子) 那条分支到这停止了。
        return newBinaryNode;
    }
	
    //先序遍历
    public static void preOrderTraversal(BinaryNode node) {
        if (node == null) 
            return; 
        System.out.print(node.data + "  ");
        preOrderTraversal(node.leftChild);
        preOrderTraversal(node.rightChild);
    }
    
    //中序遍历
    public static void inOrderTraversal(BinaryNode node) {
        if (node == null) 
            return; 
        inOrderTraversal(node.leftChild);
        System.out.print(node.data + "  ");
        inOrderTraversal(node.rightChild);
    }
    
    //后序遍历
    public static void postOrderTraversal(BinaryNode node) {
        if (node == null) 
            return;
        postOrderTraversal(node.leftChild);
        postOrderTraversal(node.rightChild);
        System.out.print(node.data + "  ");
    }
	
    public static void main(String[] args) {
        try {
            //创建二叉树,返回根结点
            root = createBinaryTree();
            System.out.println("创建成功!");
        } catch (Exception e) {
            System.out.println("创建失败,请检查输入是否有误!");
            e.printStackTrace();
        }
        //分别用3种遍历方式,打印结果
        System.out.println("先序遍历:");
        preOrderTraversal(root);
        System.out.println();
        System.out.println("中序遍历:");
        inOrderTraversal(root);
        System.out.println();
        System.out.println("后序遍历:");
        postOrderTraversal(root);
    }
}

从代码中看到输入的就是 AB#DG##H##CE##FI### ,让我们看下执行结果:

创建成功!
先序遍历:
A  B  D  G  H  C  E  F  I  
中序遍历:
B  G  D  H  A  E  C  I  F  
后序遍历:
G  H  D  B  E  I  F  C  A

从结果看创建成功,遍历结果也与开始的一致:

先序遍历:ABDGHCEFI
中序遍历:BGDHAECIF
后序遍历:GHDBEIFCA