树的前序、中序遍历的递归和非递归实现

来源:互联网 发布:php 淘宝csv导入源码 编辑:程序博客网 时间:2024/06/05 01:04

前言

我们知道,树是一种非常重要的数据结构,在各种竞赛和各大企业笔试题中,关于树,特别是二叉树的题目出现频率都很高。

今天我们来掌握二叉树的前序、中序遍历,并且给出递归和非递归两种实现。

用节点表示树

package org.lanqiao.algo;public class TreeNode<T> {  public T val ;  public TreeNode<T> left = null;  public TreeNode<T> right = null;  public TreeNode(T val) {    this.val = val;  }}

中序遍历

所谓中序遍历,是根节点居中出现的一种遍历方式,遵循左-根-右的原则。

递归形式:

public static void inorderIter(TreeNode node, Consumer consumer) {    if (null != node.left)      inorderIter(node.left, consumer);    consumer.accept(node.val);    if (null != node.right)      inorderIter(node.right, consumer);  }

比较复杂的是非递归形式,非递归形式要借用栈这种结构:

  • 先顺着根节点把所有左支路的节点压入栈中,这时,栈顶是最左的叶子节点
  • 接下来开始弹弹弹
    • 首先弹出的肯定是最左叶子
    • 弹出来的对象供消费
    • 重点来了,如果弹出的节点有右孩子,就暂停弹出,应该从这个右孩子开始回到步骤起点,把右孩子作为起点重新来一轮
  public static void inorderIterNoRecursion(TreeNode node, Consumer consumer) {    Stack<TreeNode> stack = new Stack<>();    TreeNode curr = node;    while (curr != null) {      // 顺着当前节点将左支路的节点从上往下加入栈中,最后:最左叶子节点在栈顶      while (curr != null) {        stack.add(curr);        curr = curr.left;      }      //接下来开始弹弹弹,首先弹出的肯定是最左叶子      while (!stack.isEmpty()) {        TreeNode pop = stack.pop();        consumer.accept(pop.val);// 弹出来的对象供消费        //重点来了,如果弹出的节点有右孩子,就暂停弹出,应该从右孩子开始回到外层循环的起点,把右孩子作为起点重新来一轮        if (pop.right != null) {          curr = pop.right;          break;        }      }    }  }

前序遍历

前序遍历,是根节点靠前出现的一种形式,遵循根-左-右的原则。

递归形式:

  public static void preIter(TreeNode<Integer> node) {    System.out.print(node.val + "\t");    if (null != node.left)      preIter(node.left);    if (null != node.right)      preIter(node.right);  }

非递归形式:

  • 根节点入栈
  • 循环开始
    • 弹出栈顶
    • 栈顶的右孩子入栈
    • 栈顶的左孩子入栈
    • 栈空结束循环
public static void preIterNoRecursion(TreeNode<Integer> node) {    TreeNode curr = node;    Stack<TreeNode> stack = new Stack<>();    stack.add(curr);    while (!stack.isEmpty()) {      //弹出栈顶      TreeNode pop = stack.pop();      System.out.print(pop.val + "\t");      if (pop.right != null) {        stack.add(pop.right);      }      if (pop.left != null) {        stack.add(pop.left);      }    }  }

牢记这些代码,一些关于树遍历的变种题,会比较好解

阅读全文
1 0
原创粉丝点击