Algorithms_二叉树的前序遍历、中序遍历、后续遍历(深度优先)

简介: Algorithms_二叉树的前序遍历、中序遍历、后续遍历(深度优先)


前序、中序、后序的含义

前序遍历: 先输出父节点,再遍历左子树,最后遍历右子树

中序遍历 : 先遍历左子树,再输出父节点,最后遍历右子树

后序遍历 : 先遍历左子树,再遍历右子树,最后输出父节点

如何区分呢?

输出父节点的顺序 ,就可以确定是 前序、中序、后序


实例

我们先来分析下 将 下面的几个数 放到 二分搜索树中会是怎样的存放 。

注意我们这里用的是二分搜索树来演示二叉树的这个遍历,才会有中序遍历的那个排序的特征。

5     
          /   \   
         3     6   
        / \      \ 
       2   4      8

前序遍历: 5 、3、2、4、6、8

中序遍历: 2、3、4、5、6、8

后序遍历 : 2、4、3、8、6、5

其实 , 前序遍历比较常用。

观察中序遍历,可以看到是排序的 ,这个也很好理解。 毕竟是 左侧的都是小于父节点的,右侧都是大于父节点的。

后序遍历的适用场景,举个例子 为二分搜索树释放内存

前序遍历、中序遍历、后续遍历本质上一种深度遍历


Code (递归)

前序遍历

/**
   * 
   * 
   * @Title: preOrder
   * 
   * @Description: 二分搜索树的前序遍历
   * 
   * 
   * @return: void
   */
  public void preOrder() {
    preOrder(root);
  }
  /**
   * 
   * 
   * @Title: preOrder
   * 
   * @Description: 前序遍历以node为根的二分搜索树, 递归算法
   * 
   * @param node
   * 
   * @return: void
   */
  private void preOrder(Node node) {
    if (node == null) // 终止条件
      return;
    System.out.print(node.e + "--"); // 先输出父节点
    preOrder(node.left); // 再遍历左子树
    preOrder(node.right); // 最后遍历又子树
  }

中序遍历

/**
   * 
   * 
   * @Title: inOrder
   * 
   * @Description: 二分搜索树的中序遍历
   * 
   * 
   * @return: void
   */
  public void inOrder() {
    inOrder(root);
  }
  /**
   * 
   * 
   * @Title: inOrder
   * 
   * @Description: 中序遍历以node为根的二分搜索树, 递归算法
   * 
   * @param node
   * 
   * @return: void
   */
  private void inOrder(Node node) {
    if (node == null) // 终止条件
      return;
    inOrder(node.left);
    System.out.println(node.e);
    inOrder(node.right);
  }

后序遍历

/**
   * 
   * 
   * @Title: postOrder
   * 
   * @Description: 二分搜索树的后序遍历
   * 
   * 
   * @return: void
   */
  public void postOrder() {
    postOrder(root);
  }
  /**
   * 
   * 
   * @Title: postOrder
   * 
   * @Description: 后序遍历以node为根的二分搜索树, 递归算法
   * 
   * @param node
   * 
   * @return: void
   */
  private void postOrder(Node node) {
    if (node == null) // 终止条件
      return; 
    postOrder(node.left);
    postOrder(node.right);
    System.out.println(node.e);
  }

测试

public static void main(String[] args) {
    BinarySearchTree<Integer> bst = new BinarySearchTree<>();
    int[] nums = { 5, 3, 6, 8, 4, 2 };
    for (int num : nums) {
      bst.add(num);
    }
    bst.preOrder();
    System.out.println("============================");
    bst.inOrder();
    System.out.println("============================");
    bst.postOrder();
  }

Code (非递归)

不用递归也可以实现,我们要借助Stack来实现这个。 推荐使用递归的方式,代码更简洁。

这里把不用递归的代码也贴一下,供参考

/**
   * 
   * 
   * @Title: preOrderNR
   * 
   * @Description: 二分搜索树的前序遍历 非递归的方式 栈是LIFO ,前序遍历(先处理左子树,后处理右子树)
   *               ,需要先把右节点入栈,这样才能确保后处理
   * 
   * @return: void
   */
  public void preOrderNR() {
    Stack<Node> stack = new Stack<>();
    stack.push(root); // 把root入栈
    while (!stack.isEmpty()) {
      Node currentNode = stack.pop();
      System.out.println(currentNode.e);
      if (currentNode.right != null) {
        stack.push(currentNode.right);
      }
      if (currentNode.left != null) {
        stack.push(currentNode.left);
      }
    }
  }


相关文章
|
6月前
|
存储 Java
Algorithms_二叉树&二分搜索树初探
Algorithms_二叉树&二分搜索树初探
61 0
|
6月前
Algorithms_二叉树的层次遍历(广度优先)
Algorithms_二叉树的层次遍历(广度优先)
52 0
【Leetcode -94.二叉树的中序遍历 -145.二叉树的后序遍历】
【Leetcode -94.二叉树的中序遍历 -145.二叉树的后序遍历】
32 0
|
算法 Java
算法打卡Day18_leetcode _145. 二叉树的后序遍历
算法打卡Day18_leetcode _145. 二叉树的后序遍历
算法打卡Day18_leetcode _145. 二叉树的后序遍历
|
算法 Java
算法打卡Day16_leetcode _94. 二叉树的中序遍历
算法打卡Day16_leetcode _94. 二叉树的中序遍历
算法打卡Day16_leetcode _94. 二叉树的中序遍历
|
算法 Java
算法打卡Day17_leetcode _144. 二叉树的前序遍历
算法打卡Day17_leetcode _144. 二叉树的前序遍历
算法打卡Day17_leetcode _144. 二叉树的前序遍历
leetcode【二叉树—简单】 二叉树递归遍历
leetcode【二叉树—简单】 二叉树递归遍历
|
算法 Java BI
【算法】二叉树遍历算法总结:前序中序后序遍历
二叉树遍历是非常经典的算法题,也是二叉树的一道基础算法题。 但是在平常的笔试面试中,其出现的频率其实并不是特别的高,我推测是这种题目相对来说比较基础,算是一个基础知识点。 比如剑指offer中出现的后序遍历题目,是给出一个数字序列,让你判断是不是平衡二叉树后序遍历序列,这样出题的难度比直接让你写后序遍历难很多。 但是,二叉树遍历容易吗?在递归方法下,前中后序遍历都是一个思路,理解起来也比较容易。 但是只是用迭代的话,二叉树遍历其实是有难度的!,这也是为什么LeetCode会在这三题题目的下方写出进阶: 递归算法很简单,你可以通过迭代算法完成吗?这句话了。
365 0