二叉树遍历(前序遍历,中序遍历,后序遍历)

来源:互联网 发布:ubuntu极点五笔安装 编辑:程序博客网 时间:2024/05/16 23:41

原文链接:http://www.dubby.cn/detail.html?id=9056

定义树的节点类型(为节省篇幅省略了getter/setter):

public class TreeNode<T> {    private T value;    private TreeNode<T> left;    private TreeNode<T> right;}

前序遍历

前序遍历Preorder Traversal (DLR),是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。

前序遍历结果:ABDECF
已知后序遍历和中序遍历,就能确定前序遍历。

递归

public List<T> travelWithRecursion(TreeNode<T> tree) {    List<T> result = new ArrayList<>();    doTravelRecursion(tree, result);    return result;}private void doTravelRecursion(TreeNode<T> tree, List<T> result) {    if (tree == null)        return;    result.add(tree.getValue());    if (tree.getLeft() != null)        doTravelRecursion(tree.getLeft(), result);    if (tree.getRight() != null)        doTravelRecursion(tree.getRight(), result);}

非递归

public List<T> travelWithoutRecursion(TreeNode<T> tree) {    List<T> result = new ArrayList<>();    Stack<TreeNode<T>> stack = new Stack<>();    stack.push(tree);    while (!stack.empty()) {        TreeNode<T> node = stack.pop();        result.add(node.getValue());        if (node.getRight() != null) {            stack.push(node.getRight());        }        if (node.getLeft() != null) {            stack.push(node.getLeft());        }    }    return result;}

中序遍历

中序遍历Inorder Traversal (LDR)是二叉树遍历的一种,也叫做中根遍历、中序周游。在二叉树中,先左后根再右。巧记:左根右。

中序遍历结果:DBEAFC

递归

public List<T> travelWithRecursion(TreeNode<T> tree) {    List<T> result = new ArrayList<>();    doTravelRecursion(tree, result);    return result;}private void doTravelRecursion(TreeNode<T> tree, List<T> result) {    if (tree == null)        return;    if (tree.getLeft() != null)        doTravelRecursion(tree.getLeft(), result);    result.add(tree.getValue());    if (tree.getRight() != null)        doTravelRecursion(tree.getRight(), result);}

非递归

public List<T> travelWithoutRecursion(TreeNode<T> tree) {    List<T> result = new ArrayList<>();    Stack<TreeNode<T>> stack = new Stack<>();    TreeNode<T> node = tree;    while (!stack.empty() || node != null) {        while (node != null) {            stack.push(node);            node = node.getLeft();        }        if (!stack.empty()) {            node = stack.pop();            result.add(node.getValue());            node = node.getRight();        }    }    return result;}

后序遍历

后序遍历Postorder Traversal (LRD)是二叉树遍历的一种,也叫做后根遍历、后序周游,可记做左右根。后序遍历有递归算法和非递归算法两种。在二叉树中,先左后右再根。巧记:左右根。

后序遍历结果:DEBFCA
已知前序遍历和中序遍历,就能确定后序遍历。

递归

public List<T> travelWithRecursion(TreeNode<T> tree) {    List<T> result = new ArrayList<>();    doTravelRecursion(tree, result);    return result;}private void doTravelRecursion(TreeNode<T> tree, List<T> result) {    if (tree == null)        return;    if (tree.getLeft() != null)        doTravelRecursion(tree.getLeft(), result);    if (tree.getRight() != null)        doTravelRecursion(tree.getRight(), result);    result.add(tree.getValue());}

非递归

public List<T> travelWithoutRecursion(TreeNode<T> tree) {    List<T> result = new ArrayList<>();    Stack<TreeNode<T>> stack = new Stack<>();    TreeNode<T> currentNode = tree;    TreeNode<T> lastNode = null;    while (currentNode != null) {        stack.push(currentNode);        currentNode = currentNode.getLeft();    }    while (!stack.empty()) {        currentNode = stack.pop();        //只有“当前节点”没有右孩子或者右孩子已经被访问过了,才可以访问“当前节点”        if (currentNode.getRight() == null || currentNode.getRight() == lastNode) {            result.add(currentNode.getValue());            lastNode = currentNode;        } else {            stack.push(currentNode);            currentNode = currentNode.getRight();            while (currentNode != null) {                stack.push(currentNode);                currentNode = currentNode.getLeft();            }        }    }    return result;}

测试

public class Test {    public static void main(String[] args) {        TreeNode<String> root = prepareData();        PreOrder<String> preOrder = new PreOrder<>();        InOrder<String> inOrder = new InOrder<>();        PostOrder<String> postOrder = new PostOrder<>();        System.out.println("先序遍历\t\t" + String.join(", ", preOrder.travelWithoutRecursion(root)));        System.out.println("先序遍历\t\t" + String.join(", ", preOrder.travelWithRecursion(root)));        System.out.println();        System.out.println("中序遍历\t\t" + String.join(", ", inOrder.travelWithoutRecursion(root)));        System.out.println("中序遍历\t\t" + String.join(", ", inOrder.travelWithRecursion(root)));        System.out.println();        System.out.println("后序遍历\t\t" + String.join(", ", postOrder.travelWithoutRecursion(root)));        System.out.println("后序遍历\t\t" + String.join(", ", postOrder.travelWithRecursion(root)));        System.out.println();    }    /**     *          1     *    2             3     * 4     5       6    7     */    private static TreeNode<String> prepareData() {        TreeNode<String> root = new TreeNode<>();        root.setValue("1");        TreeNode<String> node1 = new TreeNode<>();        node1.setValue("2");        root.setLeft(node1);        TreeNode<String> node1_1 = new TreeNode<>();        node1_1.setValue("4");        node1.setLeft(node1_1);        TreeNode<String> node1_2 = new TreeNode<>();        node1_2.setValue("5");        node1.setRight(node1_2);        TreeNode<String> node2 = new TreeNode<>();        node2.setValue("3");        root.setRight(node2);        TreeNode<String> node2_1 = new TreeNode<>();        node2_1.setValue("6");        node2.setLeft(node2_1);        TreeNode<String> node2_2 = new TreeNode<>();        node2_2.setValue("7");        node2.setRight(node2_2);        return root;    }}

结果:

先序遍历        1, 2, 4, 5, 3, 6, 7先序遍历        1, 2, 4, 5, 3, 6, 7中序遍历        4, 2, 5, 1, 6, 3, 7中序遍历        4, 2, 5, 1, 6, 3, 7后序遍历        4, 5, 2, 6, 7, 3, 1后序遍历        4, 5, 2, 6, 7, 3, 1

源代码地址:https://github.com/dubby1994/tree-traversal

参考文章

  • 二叉树前序、中序、后序遍历非递归写法的透彻解析
阅读全文
0 0