二叉树前中后遍历的非递归及递归算法、层序遍历

一、直观表现

 

以上述中,前中后序遍历顺序如下:

前序遍历(中左右):5 4 1 2 6 7 8
中序遍历(左中右):1 4 2 5 7 6 8
后序遍历(左右中):1 2 4 7 8 6 5

二、递归算法

在说二叉树的递归算法前,我们先了解下什么是递归算法

2.1 核心思想

递归算法!既要有递去的过程,也需要有归来的过程。主要总结如下三步

1.确定终止条件:

2.确定终止条件时的递归函数的参数和返回值:

3.提取重复逻辑,化大为小

2.2 递归的编程模型

模型一: 在递去的过程中解决问题
function recursion(大规模){
    if (end_condition){      // 明确的递归终止条件
        end;   // 简单情景
    }else{            // 在将问题转换为子问题的每一步,解决该步中剩余部分的问题
        solve;                // 递去
        recursion(小规模);     // 递到最深处后,不断地归来
    }
}


模型二: 在归来的过程中解决问题
function recursion(大规模){
    if (end_condition){      // 明确的递归终止条件
        end;   // 简单情景
    }else{            // 先将问题全部描述展开,再由尽头“返回”依次解决每步中剩余部分的问题
        recursion(小规模);     // 递去
        solve;                // 归来
    }
}

2.3 二叉树的遍历

2.3.1 前序遍历

public static void preOrderRecur(TreeNode head) {
    if (head == null) {//2.确定
        return;//1.确定函数的返回值
    }
    //3.递归的真正处理逻辑
    //3.1 先中
    System.out.print(head.value + " ");
    //3.2 再左
    preOrderRecur(head.left);
    //3.2 再右
    preOrderRecur(head.right);
}

2.3.2 中序遍历 

public static void preOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    preOrderRecur(head.left);
    System.out.print(head.value + " ");
    preOrderRecur(head.right);
}

2.3.3 后序遍历

public static void postOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    postOrderRecur(head.left);
    postOrderRecur(head.right);
    System.out.print(head.value + " ");
}

三、迭代算法

问题的递归实现转换成非递归实现一般需要两步工作:

   (1). 自己建立“堆栈(一些局部变量)”来保存这些内容以便代替系统栈,比如树的三种非递归遍历方式;

   (2). 把对递归的调用转变为对循环处理。

3.1 前序遍历的迭代算法

思想:按照先处理中间节点、再使用栈的数据结构,按右节点、左节点入栈

步骤操作
1打印节点5节点6、节点4
2打印节点4节点6、节点2、节点1
3打印节点1节点6、节点2
4打印节点2节点6
5打印节点6节点8、节点7
6打印节点7节点8
7打印节点8null
public static void preOrderIteration(TreeNode head) {
	if (head == null) {
		return;
	}
	Stack<TreeNode> stack = new Stack<>();
	stack.push(head);
	while (!stack.isEmpty()) {
		TreeNode node = stack.pop();
		System.out.print(node.value + " ");
		if (node.right != null) {
			stack.push(node.right);
		}
		if (node.left != null) {
			stack.push(node.left);
		}
	}
}

四、层序遍历

题目:

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回:

[3,9,20,15,7]

 解题思路,层序遍历时需要一个容器,队列(先进先出)

步骤操作
1打印节点3节点9、节点20
2打印节点9节点20
3打印节点20节点15、节点7
4打印节点15节点7
5打印节点7null

代码思路

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] levelOrder(TreeNode root) {
        if(root == null) return new int[0];
        int[] res;
        List<Integer> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            list.add(node.val);//打印节点
            if(node.left != null)
                queue.add(node.left);//左子树入队
            if(node.right != null)
                queue.add(node.right);右子树入队
        }
        Integer[] arr = list.toArray(new Integer[list.size()]);
        res = new int[arr.length];
        for(int i = 0; i < arr.length; i ++)
            res[i] = arr[i];
        return res;
    }
}

题目2: 

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:


输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
示例 2:

输入:root = [1]
输出:[[1]]
示例 3:

输入:root = []
输出:[]

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();//定义外层
        if (root == null) {
            return ret;
        }

        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> level = new ArrayList<Integer>();//定义内层
            int currentLevelSize = queue.size();
            for (int i = 1; i <= currentLevelSize; ++i) {
                TreeNode node = queue.poll();
                level.add(node.val);
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            ret.add(level);
        }
        
        return ret;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值