引入:

这里我们来复习下二叉树的基本操作,这里假定我们定义一个有序二叉树,就是对于任意的节点,其如果有左子节点,那么左子节点的值一定小于该节点,如果有右子节点,则右子节点的值一定大于该节点。我们这里还给出代码表明如何前序,中序,后序来遍历这个二叉树。


实践:

我们先定义一个二叉树节点的类:

package com.charles.algo.binarytree;
/**
 * 这个类定义了一个二叉树的节点
 * @author charles.wang
 *
 */
public class BinaryTreeNode {
                                                                                                                                                                                           
    //二叉树中当前节点的内容
    private Object data;
    //二叉树的左子节点
    private BinaryTreeNode leftChild;
    //二叉树的右子节点
    private BinaryTreeNode rightChild;
                                                                                                                                                                                           
    public BinaryTreeNode(Object data,BinaryTreeNode leftChild,BinaryTreeNode rightChild){
        this.data =data;
        this.leftChild=leftChild;
        this.rightChild=rightChild;
    }
                                                                                                                                                                                           
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
    public BinaryTreeNode getLeftChild() {
        return leftChild;
    }
    public void setLeftChild(BinaryTreeNode leftChild) {
        this.leftChild = leftChild;
    }
    public BinaryTreeNode getRightChild() {
        return rightChild;
    }
    public void setRightChild(BinaryTreeNode rightChild) {
        this.rightChild = rightChild;
    }
                                                                                                                                                                                           
                                                                                                                                                                                           
                                                                                                                                                                                           
                                                                                                                                                                                           
                                                                                                                                                                                         
}


然后我们定义一个二叉树类,这个二叉树提供了插入节点,前序遍历,中序遍历,后序遍历的方法:

package com.charles.algo.binarytree;
/**
 * 这里定义了一个基本的有序二叉树的数据结构
 * @author charles.wang
 *
 */
public class OrderedBinaryTree {
                                                                                                                                                               
    //用链表来实现排序二叉树的数据存储,这里放着根节点
    private BinaryTreeNode rootNode;
                                                                                                                                                               
                                                                                                                                                               
    public OrderedBinaryTree(){
        rootNode = null;
    }
                                                                                                                                                               
    /**
     * 返回当前有序二叉树的最大高度
     * @return
     */
    public int getMaxHeight(){
                                                                                                                                                                   
        return getHeight(rootNode);
                                                                                                                                                                   
    }
                                                                                                                                                               
    /**
     * 基于当前树根节点确定子树的高度,这是一个递归的方法
     * @return
     */
    private int getHeight(BinaryTreeNode currentNode){
                                                                                                                                                                   
        //如果当前树根节点为空,则返回 0
        if(currentNode==null)
            return 0;
                                                                                                                                                                   
        //如果当前树根节点不为空,那么获取左子树高度和右字数高度的最大值
        int maxLeftTreeHeight = getHeight(currentNode.getLeftChild())+1;
        int maxRightTreeHeight = getHeight(currentNode.getRightChild())+1;
        return Math.max(maxLeftTreeHeight, maxRightTreeHeight);
                                                                                                                                                                   
    }
                                                                                                                                                               
    /**
     * 插入节点到当前的有序二叉树,
     */
    public OrderedBinaryTree insertNode(Object data ){
                                                                                                                                                                   
        //如果有序二叉树中rootNode为空,那么就直接新建一个节点并且赋值给root
        if(rootNode==null){
            BinaryTreeNode binaryTreeNode = new BinaryTreeNode(data,null,null);
            rootNode=binaryTreeNode;
            return this;       
        }
                                                                                                                                                                   
        //如果有序二叉树的rootNode不为空,那么就调用递归方法进行插入
        else
            return insertNode(data,rootNode);
                                                                                                                                                                   
                                                                                                                                                                   
                                                                                                                                                                   
    }
                                                                                                                                                               
    /**
     * 递归的插入一个节点到当前节点使得仍然保持 一个有序二叉树
     */
    public OrderedBinaryTree insertNode(Object data, BinaryTreeNode rootNode){
                                                                                                                                                                   
                                                                                                                                                                   
        //创建一个代表当前待查数据的节点
        BinaryTreeNode currentNode = new BinaryTreeNode(data,null,null);
                                                                                                                                                                   
        //吧当前的数据和被插入的rootNode的大小进行比较
                                                                                                                                                                   
        //如果当前数据小于被插入的rootNode,那么这个新的数据节点必定插在rootNode的左边
        if( (Integer)data< (Integer)rootNode.getData()){
                                                                                                                                                                       
            //如果待插的rootNode的左节点为空,那么直接插入
            if(rootNode.getLeftChild()==null){
                rootNode.setLeftChild(currentNode);
                return this;
            }
            //如果待插的rotNode的左节点不为空,则递归的吧待插入点设为root的左节点,然后递归的调用方法插入
            else
                return insertNode(data ,rootNode.getLeftChild());
        }
                                                                                                                                                                   
        //如果当前数据大于被插入的rootNode,那么这个新的数据节点必定插在rootNode的右边
        else {
                                                                                                                                                                       
            //如果待插的rootNode的右边节点为空,那么直接插入
            if(rootNode.getRightChild()==null){
                rootNode.setRightChild(currentNode);
                return this;
            }
            //如果待插的rootNode的右边节点不为空,则赌鬼的吧所待插入点设为root的右节点,然后递归调用方法插入
            else
                return insertNode(data,rootNode.getRightChild());
        }
                                                                                                                                                                   
                                                                                                                                                                   
    }
                                                                                                                                                               
    /**
     * 前序遍历这个二叉树,并且打印出这个二叉树的各个节点
     */
    public void preOrderFullBinaryTree(){
        preOrder(rootNode);
    }
                                                                                                                                                               
    /**
     * 中序遍历这个二叉树,并且打印出这个二叉树的各个节点
     */
    public void midOrderFullBinaryTree(){
        midOrder(rootNode);
    }
                                                                                                                                                               
    /**
     * 后序遍历这个二叉树,并且打印出这个二叉树的各个节点
     */
    public void postOrderFullBinaryTree(){
        postOrder(rootNode);
    }
                                                                                                                                                               
    /**
     * 前序遍历某节点,它会先打印当前节点,然后打印出左边节点,然后打印出右边节点
     */
    private void preOrder(BinaryTreeNode currentNode){
                                                                                                                                                                   
        //当前的节点如果是null,则不打印出当前节点,并且退出递归
                                                                                                                                                                   
        if(currentNode!=null){
            System.out.print(currentNode.getData()+" ");   
            //遍历左边子树
            preOrder(currentNode.getLeftChild());
            //遍历右边子树
            preOrder(currentNode.getRightChild());
        }
    }
                                                                                                                                                               
    /**
     * 中序遍历某节点,它会先打印左边节点,再打印当前节点,最后打印出右边节点
     * @param args
     */
    private void midOrder(BinaryTreeNode currentNode){
                                                                                                                                                                   
        //当前节点如果是null,则不打印出当前节点,并且退出递归
        if(currentNode!=null){
            midOrder(currentNode.getLeftChild());
            System.out.print(currentNode.getData()+" ");
            midOrder(currentNode.getRightChild());
        }
    }
                                                                                                                                                               
    /**
     * 后序遍历某个节点,它会先打印出左边节点,再打印出右边节点,最后打印出当前节点
     * @param args
     */
    private void postOrder(BinaryTreeNode currentNode){
                                                                                                                                                                   
        //如果当前的节点是null,则不打印出当前节点,并且退出递归
        if(currentNode!=null){
            postOrder(currentNode.getLeftChild());
            postOrder(currentNode.getRightChild());
            System.out.print(currentNode.getData()+" ");
        }
    }
                                                                                                                                                               
                                                                                                                                                               
                                                                                                                                                               
    public static void main(String[] args){
        OrderedBinaryTree fbt = new OrderedBinaryTree();
        fbt.insertNode(12).insertNode(5).insertNode(9).insertNode(11).insertNode(8).insertNode(42).insertNode(4);
                                                                                                                                                                   
                                                                                                                                                                   
        //前序遍历所有的节点
        System.out.println("前序的方式遍历二叉树的所有的节点:");
        fbt.preOrderFullBinaryTree();
        System.out.println();
                                                                                                                                                                   
        //中序遍历所有的节点
        System.out.println ("中序的方式遍历二叉树的所有的节点:");
        fbt.midOrderFullBinaryTree();
        System.out.println();
                                                                                                                                                                   
        //后序遍历所有的节点
        System.out.println("后序的方式遍历二叉树的所有的节点:");
        fbt.postOrderFullBinaryTree();
        System.out.println();
    }
}


其实由于考虑到二叉树定义的递归性,我们上述方法都是用递归实现的,比如插入就是比较当前元素,如果插入元素比当前元素少,那么就比较当前元素的左子元素,如果左子元素不存在,那么新插入的元素就作为左子元素,否则就以左子元素为根,递归的插入该元素到左子二叉树中。反过来也一样,如果插入元素比当前元素大,那么久比较当前元素的右子元素,如果右子元素不存在,那么新插元素就作为右子元素,否则就以右子元素为根,递归的插入到该元素到右子二叉树中。


前序,中序,后序遍历也是一样的。


验证结果:

最后我们来运行这个简单的例子,果然是期望的,比如我们分别插入了果然的不一样的数,那么遍历结果顺序是不一样的但是都遍历二叉树的所有节点。

<基础巩固>二叉树的遍历_第1张图片