普通二叉树的前中后三种遍历方式

  • 什么是二叉树?

二叉树(Binary Tree)是一种树状数据结构,其中每个节点最多有两个子节点,通常称为左子节点和右子节点。每个节点包含一个值或数据元素,并可以包含指向其子节点的引用。二叉树的结构是由节点和节点之间的连接关系组成的。

二叉树的基本特点包括:

  1. 根节点(Root):二叉树的顶部节点,是整个树的起始点。

  2. 叶节点(Leaf):没有子节点的节点称为叶节点。

  3. 父节点(Parent):有子节点的节点称为父节点。

  4. 子节点(Child):父节点的下级节点称为子节点。通常分为左子节点和右子节点。

  5. 深度(Depth):节点的深度表示从根节点到该节点的路径长度,根节点的深度为0。

  6. 高度(Height):二叉树的高度表示树中最深的叶节点的深度。也可以说是从根节点到最深叶节点的最长路径的长度。

  7. 子树(Subtree):以某个节点为根的树,包括该节点及其所有后代节点。

  8. 遍历(Traversal):遍历二叉树是按照一定的顺序访问树中的节点。常见的遍历方式包括前序遍历、中序遍历和后序遍历。

不同的二叉树结构可以满足不同的需求,例如二叉搜索树(Binary Search Tree)具有有序性质,AVL 树和红黑树是平衡二叉搜索树,堆(Heap)是一种用于高效查找最小(或最大)元素的特殊二叉树,二叉树还用于构建哈夫曼树等数据压缩算法。

二叉树是计算机科学中非常重要的数据结构,用于实现各种算法和数据处理任务。

1. 前序遍历(Preorder Traversal)

前序遍历是从树的根节点开始,按照根节点、左子树、右子树(中、左、右)的顺序递归访问节点。在前序遍历中,首先访问根节点,然后依次递归遍历左子树和右子树。

public void preorderTraversal(TreeNode node) {
    if (node != null) {
        System.out.print(node.val + " "); // 访问当前节点
        preorderTraversal(node.left); // 遍历左子树
        preorderTraversal(node.right); // 遍历右子树
    }
}

2. 中序遍历(Inorder Traversal)

中序遍历是按照左子树、根节点、右子树(左、中、右)的顺序递归访问节点。在中序遍历中,首先递归遍历左子树,然后访问根节点,最后递归遍历右子树。

public void inorderTraversal(TreeNode node) {
    if (node != null) {
        inorderTraversal(node.left); // 遍历左子树
        System.out.print(node.val + " "); // 访问当前节点
        inorderTraversal(node.right); // 遍历右子树
    }
}

3. 后序遍历(Postorder Traversal)

后序遍历是按照左子树、右子树、根节点(左、右、中)的顺序递归访问节点。在后序遍历中,首先递归遍历左子树,然后递归遍历右子树,最后访问根节点。

public void postorderTraversal(TreeNode node) {
    if (node != null) {
        postorderTraversal(node.left); // 遍历左子树
        postorderTraversal(node.right); // 遍历右子树
        System.out.print(node.val + " "); // 访问当前节点
    }
}

迭代的遍历方式

除了递归方式,你也可以使用迭代方式来遍历二叉树。迭代遍历方式通常需要使用辅助数据结构,如栈(Stack)或队列(Queue),以模拟递归调用的工作栈。下面我将介绍迭代的遍历方式,并解释其思想。

1. 迭代的前序遍历(中左右)

迭代的前序遍历使用栈来模拟递归调用的顺序。基本思想是维护一个栈,首先将根节点入栈,然后进入循环,循环条件为栈不为空。在每一轮循环中,将栈顶节点出栈,访问该节点,并将右子节点和左子节点按逆序入栈,以确保下一次出栈的是左子节点。这样,根节点会被最先访问,然后是左子树,最后是右子树。

public void iterativePreorderTraversal(TreeNode root) {
    if (root == null) return;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        System.out.print(node.val + " "); // 访问当前节点
        if (node.right != null) {
            stack.push(node.right);
        }
        if (node.left != null) {
            stack.push(node.left);
        }
    }
}

当在Java中使用栈数据结构时,通常是使用java.util.Stack类,这是一个基于双链表(LinkedList)实现的栈。

如果你更喜欢使用双链表来实现栈,你可以按照以下方式修改代码:

public void iterativePreorderTraversal(TreeNode root) {
    if (root == null) return;
    LinkedList<TreeNode> stack = new LinkedList<>();//代码修改
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        System.out.print(node.val + " "); // 访问当前节点
        if (node.right != null) {
            stack.push(node.right);
        }
        if (node.left != null) {
            stack.push(node.left);
        }
    }
}
2. 迭代的中序遍历(左中右)

迭代的中序遍历也使用栈来模拟递归调用的顺序。基本思想是从根节点开始,将左子节点依次入栈,直到没有左子节点。然后出栈,访问节点,然后将右子节点入栈,重复这个过程,直到栈为空。

public void iterativeInorderTraversal(TreeNode root) {
    if (root == null) return;
    LinkedList<TreeNode> stack = new LinkedList<>();
    TreeNode current = root;
    while (current != null || !stack.isEmpty()) {
        while (current != null) {
            stack.push(current);
            current = current.left;
        }
        current = stack.pop();
        System.out.print(current.val + " "); // 访问当前节点
        current = current.right;
    }
}
3. 迭代的后序遍历(左右中)

迭代的后序遍历也使用栈来模拟递归调用的顺序。基本思想是使用两个栈。

一个用于遍历,一个用于存储结果。

首先将根节点入遍历栈,然后进入循环,循环条件为遍历栈不为空。

在每一轮循环中,将栈顶节点出栈,并将其值插入到结果栈的栈顶。然后按照根节点、右子节点、左子节点的顺序,将节点依次入遍历栈。最后,将结果栈中的元素依次出栈,即可得到后序遍历的结果。

public void iterativePostorderTraversal(TreeNode root) {
    if (root == null) return;
    LinkedList<TreeNode> traversalStack = new LinkedList<>();
    LinkedList<TreeNode> resultStack = new LinkedList<>();
    traversalStack.push(root);
    while (!traversalStack.isEmpty()) {
        TreeNode node = traversalStack.pop();
        resultStack.push(node);
        if (node.left != null) {
            traversalStack.push(node.left);
        }
        if (node.right != null) {
            traversalStack.push(node.right);
        }
    }
    while (!resultStack.isEmpty()) {
        System.out.print(resultStack.pop().val + " "); // 访问当前节点
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值