java实现二叉树遍历

2021/10/6 22:11:01

本文主要是介绍java实现二叉树遍历,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

java二叉树遍历,最复杂的是非递归的后序遍历

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.LinkedList;

public class BinaryTree<T> {
    private BinaryNode<T> root;

    public BinaryTree(BinaryNode<T> root) {
        this.root = root;
    }

    public BinaryTree() {
        this.root = null;
    }

    public boolean isEmpty() {
        return this.root == null;
    }

    public BinaryNode<T> leftChild() {
        return this.root.left;
    }

    public BinaryNode<T> rightChild() {
        return this.root.right;
    }

    public void setRoot(BinaryNode<T> root) {
        this.root = root;
    }

    public void setLeft(BinaryNode<T> left) {
        this.root.left = left;
    }

    public void setRight(BinaryNode<T> right) {
        this.root.right = right;
    }


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class BinaryNode<T> {
        private T data;
        private BinaryNode<T> left;
        private BinaryNode<T> right;
    }

    /**
     * 宽度优先遍历
     */
    public void levelOrder(BinaryNode<T> root) {
        java.util.Queue<BinaryNode<T>> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            BinaryNode<T> node = queue.remove();
            if (node == null) {
                continue;
            }
            System.out.println(node.data);
            queue.add(node.left);
            queue.add(node.right);
        }
    }

    /**
     * 先根遍历-递归实现
     *
     * @param t
     */
    public void preOrder(BinaryNode<T> t) {
        //递归结束条件
        if (t == null) {
            return;
        } else {
            System.out.println(t.data);
        }
        preOrder(t.left);
        preOrder(t.right);

    }

    /**
     * 中根遍历-递归实现
     *
     * @param t
     */
    public void midOrder(BinaryNode<T> t) {
        if (t == null) {
            return;
        }
        midOrder(t.left);
        System.out.println(t.data);
        midOrder(t.right);
    }

    /**
     * 后根遍历-递归实现
     *
     * @param t
     */
    public void postOrder(BinaryNode<T> t) {
        if (t == null) {
            return;
        }
        postOrder(t.left);
        postOrder(t.right);
        System.out.println(t.data);
    }

    /**
     * 先根遍历-非递归实现
     * 先根,然后根的左子树,一直向下左子树,此时右子树尚未访问,所有需要先暂存一下
     * 左到头了,此时需要访问最底层的右子树,只需要从栈中取出最后进栈的右子树
     * 拿到右子树之后,又是先根,然后左到底
     * 所以需要使用栈这种后进先出的数据结构
     *
     * @param t
     */
    public void preOrderNoRec(BinaryNode<T> t) {
        java.util.Stack<BinaryNode<T>> stack = new java.util.Stack<>();
        while (t != null || !stack.isEmpty()) {
            while (t != null) {
                System.out.println(t.data);
                stack.push(t.right);
                t = t.left;
            }
            t = stack.pop();
        }
    }

    /**
     * 中根遍历-非递归实现
     * 1。先左子树,一直到底,然后根节点,然后根的右子树
     * 2。根的右子树又是新的一轮循环,还是跟1一样的顺序
     *
     * @param t
     */
    public void midOrderNoRec(BinaryNode<T> t) {
        java.util.Stack<BinaryNode<T>> stack = new java.util.Stack<>();
        while (t != null || !stack.isEmpty()) {
            //递归向左
            while (t.left != null) {
                stack.push(t);
                t = t.left;
            }
            //如果有左,就左到头,打印最下的左节点
            //如果没有左节点,那么跳过上面的while循环,打印根节点
            System.out.println(t.data);
            //判断是否还有未遍历的根节点,取出然后打印当前根
            if (!stack.isEmpty()) {
                t = stack.pop();
                System.out.println(t.data);
            }
            //切到右子树
            t = t.right;
        }
    }

    /**
     * 后根遍历-非递归实现
     * 最复杂
     * @param t
     */
    public void postOrderNoRec(BinaryNode<T> t) {
        java.util.Stack<BinaryNode<T>> stack = new java.util.Stack<>();
        while (t != null || !stack.isEmpty()) {
            //t节点入栈
            while (t != null) {
                stack.push(t);
                //如果左节点不为空,则递归向左,否则递归向右
                if (t.left != null) {
                    t = t.left;
                } else {
                    t = t.right;
                }
            }
            //直到t到达既没有左也没有右,取出t打印
            t = stack.pop();
            System.out.println(t.data);
            //栈不空,且当前节点是栈顶的左子节点,切换到右子树
            //如果父节点尚未访问,且当前是父节点的左孩子,递归访问父节点的右孩子
            //否则说明本节点是右孩子,结束本轮循环,从栈顶再重新取一个节点开始
            if (!stack.isEmpty() && stack.peek().left == t) {
                t = stack.peek().right;
            } else {
                t = null;
            }
        }
    }

    public static void main(String[] args) {
        BinaryTree<Integer> tree = new BinaryTree<>();
        BinaryNode<Integer> root = new BinaryNode<>(1, null, null);
        BinaryNode<Integer> leftL = new BinaryNode<>(4, null, null);
        BinaryNode<Integer> leftR = new BinaryNode<>(5, null, null);
        BinaryNode<Integer> left = new BinaryNode<>(2, leftL, leftR);
        BinaryNode<Integer> rightL = new BinaryNode<>(6, null, null);
        BinaryNode<Integer> rightR = new BinaryNode<>(7, null, null);
        BinaryNode<Integer> right = new BinaryNode<>(3, rightL, rightR);
        tree.setRoot(root);
        tree.setLeft(left);
        tree.setRight(right);
        System.out.println("=======levelOrder=========");
        tree.levelOrder(tree.root);
//        System.out.println("=======preOrder=========");
//        tree.preOrder(tree.root);
//        System.out.println("=======midOrder=========");
//        tree.midOrder(tree.root);
        System.out.println("=======postOrder=========");
        tree.postOrder(tree.root);
//        System.out.println("=======preOrderNoRec=========");
//        tree.preOrderNoRec(tree.root);
//        System.out.println("=========midOrderNoRec===============");
//        tree.midOrderNoRec(tree.root);
        System.out.println("==========================");
        tree.postOrderNoRec(tree.root);

    }
}

 



这篇关于java实现二叉树遍历的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程