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

本文详细介绍了二叉树的前序、中序和后序遍历算法,包括递归和非递归实现方式,并提供了具体的Java代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接: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

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值