二叉树的递归和非递归遍历

二叉树的递归遍历代码是很直观的,但是非递归遍历时不是那么直观,特别是中序遍历和后续遍历。

中序遍历非递归实现

中序遍历需要先访问左节点,然后访问根节点,最后访问右节点。
我们参考递归代码找寻思路:

1. if (root == null) {return;} 
2. midOrder(root.leftChild);
3. System.out.println(root.data);
4. midOrder(root.rightChild);

递归先找到最左面的节点,这里我们可以while和栈模拟实现

//对应递归第二句  midOrder(root.leftChild);
while (root != null) {
       stack.push(root);
       root = root.leftChild;
}

root为空意味着我们要出栈,因此可以下面代码模拟递归函数返回:

//对应递归算法第一句 if (root == null) {return;}
//递归算法里走到上面这的时候,代表root.leftChild == null,return返回上一次调用
root = stack.pop();
//对应递归算法第三句
System.out.println(root.data);

之后,递归算法将右节点传入继续执行递归,所以我们需要root = root.rightChild,然后将root重新执行上面算法,因此我们需要将上面算法再用一层while套住。

最终的非递归实现:

private void midOrder2(Node<T> root) {
        if (root == null) {
            return;
        }
        Stack<Node<T>> stack = new Stack<>();
        while (root != null || !stack.empty()) {
            //模拟递归入栈
            while (root != null) {
                stack.push(root);
                root = root.leftChild;
            }
            root = stack.pop();
            System.out.println(root.data);
            root = root.rightChild;
        }
    }
/**
 * Created by 默默 on 2018/3/1.
 */

import java.util.Stack;

public class BinaryTree<T> {
    public static class Node<T> {
        T data;
        Node<T> leftChild;
        Node<T> rightChild;

        public Node(T data, Node<T> leftChild, Node<T> rightChild) {
            super();
            this.data = data;
            this.leftChild = leftChild;
            this.rightChild = rightChild;
        }
    }

    public Node<T> root;

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

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

    /**
     * 递归实现
     *
     * @param root
     */
    private void preOrder(Node<T> root) {
        if (root == null) {
            return;
        }
        System.out.println(root.data);
        preOrder(root.leftChild);
        preOrder(root.rightChild);
    }

    public void preOrder2() {
        preOrder2(root);
    }

    /**
     * 栈实现
     */
    private void preOrder2(Node<T> root) {
        if (root == null) {
            return;
        }
        Stack<Node<T>> stack = new Stack<>();
        stack.push(root);
        while (!stack.empty()) {
            Node<T> node = stack.pop();
            System.out.println(node.data);
            if (node.rightChild != null) {
                stack.push(node.rightChild);
            }
            if (node.leftChild != null) {
                stack.push(node.leftChild);
            }
        }
    }

    public void midOrder() {
        midOrder(root);
    }

    private void midOrder(Node<T> root) {
        if (root == null) {
            return;
        }
        midOrder(root.leftChild);
        System.out.println(root.data);
        midOrder(root.rightChild);
    }

    public void midOrder2() {
        midOrder2(root);
    }

    /**
     * 栈实现中序遍历
     */
    private void midOrder2(Node<T> root) {
        if (root == null) {
            return;
        }
        Stack<Node<T>> stack = new Stack<>();
        while (root != null || !stack.empty()) {
            //模拟递归入栈
            while (root != null) {
                stack.push(root);
                root = root.leftChild;
            }
            root = stack.pop();
            System.out.println(root.data);
            root = root.rightChild;
        }
    }

    public void postOrder2() {
        postOrder2(root);
    }

    private void postOrder2(Node<T> root) {
        if (root == null) {
            return;
        }
        Stack<Node<T>> stack = new Stack<>();
        Node<T> lastVisitedNode = null;
        while (root != null || !stack.empty()) {
            //一直到左子树最下边
            while (root != null) {
                stack.push(root);
                root = root.leftChild;
            }
            Node<T> node = stack.pop();
            /**
             * 右子树不为空并且还没有被访问,当前节点重新入栈,访问右节点
             */
            if (node.rightChild != null && node.rightChild != lastVisitedNode) {
                stack.push(node);
                root = node.rightChild;
            } else {
                System.out.println(node.data);
                root = null;
                记录上一次访问的节点
                lastVisitedNode = node;
            }
        }
    }

    public static void main(String[] args) {
        /**
         *           A
         *          / \
         *         B   C
         *        /   / \
         *       D   E   F
         *      / \   \
         *     G   H   I
         */
        Node<String> gNode = new Node<String>("G", null, null);
        Node<String> hNode = new Node<String>("H", null, null);
        Node<String> iNode = new Node<String>("I", null, null);
        Node<String> fNode = new Node<String>("F", null, null);
        Node<String> dNode = new Node<String>("D", gNode, hNode);
        Node<String> eNode = new Node<String>("E", null, iNode);
        Node<String> bNode = new Node<String>("B", dNode, null);
        Node<String> cNode = new Node<String>("C", eNode, fNode);
        Node<String> root = new Node<String>("A", bNode, cNode);
        BinaryTree<String> tree = new BinaryTree<String>(root);
        //ABDGHCEIF
        //tree.preOrder2();
        //GDHBAEICF
        //tree.midOrder2();
        //GHDBIEFCA
        //tree.postOrder2();
    }
}

猜你喜欢

转载自blog.csdn.net/momo_ibeike/article/details/79414754