二叉树以及前序、中序、后序、层序遍历(JAVA)

二叉树

public interface BTree<E> {

    /**
     * 树中的节点个数
     * @return
     */
    int size();

    /**
     * 树是否为空
     * @return
     */
    boolean isEmpty();

    /**
     * 前序遍历
     * 中左右
     */
    void preOrder();

    /**
     * 中序遍历
     * 左中右
     */
    void inOrder();

    /**
     * 后续遍历
     * 左右中
     */
    void postOrder();

    /**
     * 层序遍历
     */
    void levelOrder();

    /**
     *       A
     *     /  \
     *   B    C
     *  / \  / \
     * D  E F  G
     *
     * 前序遍历结果:A-B-D-E-C-F-G
     * 中序遍历结果:D-B-E-A-F-C-G
     * 后序遍历结果:D-E-B-F-G-C-A
     * 层序遍历结果:A-B-C-D-E-F-G
     */

}

基于数组:顺序二叉树
基于链表:链式二叉树

顺序二叉树

  1. 根节点存储在index = 1
  2. 某节点存储在index = i,那么其左子节点将存储在index = 2*i,其右子节点将存储在index = 2*i + 1,其父节点将存储在index = i/2
import java.util.LinkedList;
import java.util.Queue;

public class ArrayBTree<E> implements BTree<E> {

    private E[] array;

    /**
     * 暂时不考虑扩展性,这里基于数组的二叉树是配角
     * 等它成主角了再改
     */
    public ArrayBTree() {
        array = (E[]) new Object[10];
    }

    public ArrayBTree<String> testBTree() {
        /**
         *            A
         *          B   C
         *       D  E  F  G
         */
        ArrayBTree<String> btree = new ArrayBTree<>();
        String[] arr = {"A", "B", "C", "D", "E", "F", "G"};
        for (int i = 0; i < arr.length; i++) {
            Object[] array = btree.array;
            array[i + 1] = arr[i];
        }
        return btree;
    }

    @Override
    public int size() {
        return array.length - 1;
    }

    @Override
    public boolean isEmpty() {
        return size() == 0;
    }

    private int parentIndex(int sonIndex) {
        return sonIndex >> 1;
    }

    private int leftIndex(int parentIndex) {
        return parentIndex << 1;
    }

    private int rightIndex(int parentIndex) {
        return leftIndex(parentIndex) + 1;
    }

    @Override
    public void preOrder() {
        preOrder(1);
    }

    private void preOrder(int index) {
        if (index > size() || array[index] == null) {
            return;
        }

        int left = leftIndex(index);
        int right = rightIndex(index);
        System.out.println(array[index]);
        preOrder(left);
        preOrder(right);
    }

    @Override
    public void inOrder() {
        inOrder(1);
    }

    private void inOrder(int index) {
        if (index > size() || array[index] == null) {
            return;
        }

        int left = leftIndex(index);
        int right = rightIndex(index);
        inOrder(left);
        System.out.println(array[index]);
        inOrder(right);
    }

    @Override
    public void postOrder() {
        postOrder(1);
    }

    private void postOrder(int index) {
        if (index > size() || array[index] == null) {
            return;
        }

        int left = leftIndex(index);
        int right = rightIndex(index);
        postOrder(left);
        postOrder(right);
        System.out.println(array[index]);
    }

    /**
     * 层序遍历
     */
    @Override
    public void levelOrder() {
        Queue<Integer> queue = new LinkedList<>();
        queue.add(1);
        while (!queue.isEmpty()) {
            Integer poll = queue.poll();
            System.out.println(array[poll]);

            int left = leftIndex(poll);
            if (left < array.length && array[left] != null) {
                queue.add(left);
            }

            int right = rightIndex(poll);
            if (right < array.length && array[right] != null) {
                queue.add(right);
            }
        }
    }

    public static void main(String[] args) {
        ArrayBTree<String> bTree = new ArrayBTree<>();
        bTree = bTree.testBTree();
        System.out.println("preOrder");
        bTree.preOrder();
        System.out.println("inOrder");
        bTree.inOrder();
        System.out.println("postOrder");
        bTree.postOrder();
        System.out.println("levelOrder");
        bTree.levelOrder();
    }

}

链式二叉树

import java.util.LinkedList;
import java.util.Queue;

public class LinkedBTree<E> implements BTree<E> {

    private class Node<E> {
        public E val;
        public Node<E> left, right;

        public Node(E e) {
            val = e;
            left = right = null;
        }
    }

    private Node<E> root;
    private int size;

    public LinkedBTree() {
        root = null;
        size = 0;
    }

    public LinkedBTree<String> testBTree() {
        /**
         *            A
         *          B   C
         *       D  E  F  G
         */
        LinkedBTree<String> btree = new LinkedBTree<>();
        btree.root = btree.new Node<String>("A");
        btree.root.left = btree.new Node<String>("B");
        btree.root.right = btree.new Node<String>("C");
        btree.root.left.left = btree.new Node<String>("D");
        btree.root.left.right = btree.new Node<String>("E");
        btree.root.right.left = btree.new Node<String>("F");
        btree.root.right.right = btree.new Node<String>("G");

        btree.size = 7;

        return btree;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public void preOrder() {
        preOrder(root);
    }

    private void preOrder(Node<E> node) {
        if (node == null) {
            return;
        }

        System.out.println(node.val);
        preOrder(node.left);
        preOrder(node.right);
    }

    @Override
    public void inOrder() {
        inOrder(root);
    }

    private void inOrder(Node<E> node) {
        if (node == null) {
            return;
        }

        inOrder(node.left);
        System.out.println(node.val);
        inOrder(node.right);
    }

    @Override
    public void postOrder() {
        postOrder(root);
    }

    private void postOrder(Node<E> node) {
        if (node == null) {
            return;
        }

        postOrder(node.left);
        postOrder(node.right);
        System.out.println(node.val);
    }

    /**
     * 层序遍历
     */
    @Override
    public void levelOrder() {
        Queue<Node<E>> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            Node<E> poll = queue.poll();
            System.out.println(poll.val);

            if (poll.left != null) {
                queue.add(poll.left);
            }

            if (poll.right != null) {
                queue.add(poll.right);
            }
        }
    }

    public static void main(String[] args) {
        LinkedBTree<String> bTree = new LinkedBTree<>();
        bTree = bTree.testBTree();
        System.out.println("preOrder");
        bTree.preOrder();
        System.out.println("inOrder");
        bTree.inOrder();
        System.out.println("postOrder");
        bTree.postOrder();
        System.out.println("levelOrder");
        bTree.levelOrder();
    }

}

前序遍历、中序遍历、后续遍历中的前中后是针对当前节点而言的,当前节点先输出就是前序遍历(中左右),当前节点后输出就是后续遍历(左右中)

前序、中序、后序遍历的非递归实现

这里的非递归实现针对底层是链表的二叉树

前序遍历

/**
 * 前序遍历非递归实现
 */
public void preOrderNonRecursive() {
    Stack<Node> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        Node cur = stack.pop();
        System.out.println(cur.val);
        if (cur.right != null) {
            stack.push(cur.right);
        }
        if (cur.left != null) {
            stack.push(cur.left);
        }
    }
}

中序遍历

/**
 * 中序遍历非递归实现
 */
public void inOrderNonRecursive() {
    Stack<Node> stack = new Stack<>();

    Node cur = root;
    while (cur != null || !stack.isEmpty()) {
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }

        if (!stack.isEmpty()) {
            Node pop = stack.pop();
            System.out.println(pop.val);
            cur = pop.right;
        }
    }
}

上述代码等价于

/**
 * 中序遍历非递归实现
 */
public void inOrderNonRecursive() {
    Stack<Node> stack = new Stack<>();

    Node cur = root;
    while (cur != null || !stack.isEmpty()) {
        if (cur != null) {
            stack.push(cur);
            cur = cur.left;
        } else {
            Node pop = stack.pop();
            System.out.println(pop.val);
            cur = pop.right;
        }
    }
}

后序遍历

/**
 * 后序遍历非递归实现
 */
public void postOrderNonRecursive() {
    Stack<Node> stack = new Stack<>();
    Set<Node> rightFlags = new HashSet<>();

    Node cur = root;
    while (cur != null || !stack.isEmpty()) {
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }

        if (!stack.isEmpty()) {
            Node pop = stack.peek();
            if (rightFlags.contains(pop)) {
                // 如果访问过当前节点的右子树,直接打印
                stack.pop();
                System.out.println(pop.val);
                rightFlags.remove(pop);
            } else {
                // 如果没访问过当前节点的右子树,将cur赋值给右子树
                rightFlags.add(pop);
                cur = pop.right;
            }
        }
    }
}

双栈法

/**
 * 后序遍历非递归实现
 */
public void postOrderNonRecursive() {
    Stack<Node> stack1 = new Stack<>();
    Stack<Node> stack2 = new Stack<>();

    stack1.push(root);
    while (!stack1.isEmpty()) {
        Node pop = stack1.pop();
        // 入stack2
        stack2.push(pop);
        // 先左
        if (pop.left != null) {
            stack1.push(pop.left);
        }
        // 再右
        if (pop.right != null) {
            stack1.push(pop.right);
        }
        // 这样等到左右入stack2时,就成了“中-右-左”
        // 最终出stack2时就成了“左-右-中”,即后序遍历
    }

    while (!stack2.isEmpty()) {
        System.out.println(stack2.pop().val);
    }
}

令我眼前一亮的前中后序非递归遍历的实现

定义一个指令类

class Msg {
    static final boolean GO = false;
    static final boolean PRINT = true;
    boolean go; // false表示访问,true表示打印
    Node node;

    Msg(boolean go, Node node) {
        this.go = go;
        this.node = node;
    }
}

前序

public void preOrderNonRecursive2() {
    LinkedList<Msg> stack = new LinkedList<>();
    stack.push(new Msg(Msg.GO, root));

    while (!stack.isEmpty()) {
        Msg pop = stack.pop();
        if (Msg.PRINT == pop.go) {
            System.out.println(pop.node.val);
        } else {
            // 以右左中入栈
            if (pop.node.right != null) {
                stack.push(new Msg(Msg.GO, pop.node.right));
            }
            if (pop.node.left != null) {
                stack.push(new Msg(Msg.GO, pop.node.left));
            }
            stack.push(new Msg(Msg.PRINT, pop.node));
        }
    }
}

中序

public void inOrderNonRecursive2() {
    LinkedList<Msg> stack = new LinkedList<>();
    stack.push(new Msg(Msg.GO, root));

    while (!stack.isEmpty()) {
        Msg pop = stack.pop();
        if (Msg.PRINT == pop.go) {
            System.out.println(pop.node.val);
        } else {
            // 以右中左入栈
            if (pop.node.right != null) {
                stack.push(new Msg(Msg.GO, pop.node.right));
            }
            stack.push(new Msg(Msg.PRINT, pop.node));
            if (pop.node.left != null) {
                stack.push(new Msg(Msg.GO, pop.node.left));
            }
        }
    }
}

后序

public void postOrderNonRecursive2() {
    LinkedList<Msg> stack = new LinkedList<>();
    stack.push(new Msg(Msg.GO, root));

    while (!stack.isEmpty()) {
        Msg pop = stack.pop();
        if (Msg.PRINT == pop.go) {
            System.out.println(pop.node.val);
        } else {
            // 以中右左入栈
            stack.push(new Msg(Msg.PRINT, pop.node));
            if (pop.node.right != null) {
                stack.push(new Msg(Msg.GO, pop.node.right));
            }
            if (pop.node.left != null) {
                stack.push(new Msg(Msg.GO, pop.node.left));
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值