二叉树的先序-中序-后序遍历(一)-递归

这几天在复习算法,又遇到树的遍历。

树的遍历递归比较简单;循环就比较麻烦了,看了别人的写法老是想不通是怎么做到的。

今天静下心来想想,得出了自己的一套“白痴”的方案。


--本篇先讲简单的---递归遍历。


一、预备知识

树的遍历方式:

1.先序遍历:对于一个节点,1读本身,2读左子,3读右子。

2.中序遍历:对于一个节点,1读左子,2读本身,3读右子。

3.后序遍历:对于一个节点,1读左子,2读右子,3读本身。


怎么记:

不管怎么样,左子肯定在右子前面;先序中序后序,指的是本身节点放在第一个、第二个还是第三个。

那位置不就确定下来了吗?


二、先想好用递归怎么做

想要用递归来做树的遍历,那这个时候眼里就只有一个节点。

那好,现在手里拿着一个树节点,我会怎么做(左中右为例)?

1.把事情扔给左节点去做。

2.左边的处理完了,轮到自己了,读取本身节点。

3.把事情扔给左节点去做。


三、动手

先把环境搭一下:

3个类,一个TreeNode实体类,一个遍历的工具类,一个测试专用类

1.TreeNode类

package com.aii.algorithm;

public class TreeNode {
	int value;
	TreeNode left;
	TreeNode right;

	@Override
	public String toString() {
		return "TreeNode [value=" + value + "]";
	}

	public TreeNode() {
	}

	public TreeNode(int value) {
		this.value = value;
	}

}

2.遍历的工具类

package com.aii.algorithm;

import java.util.Queue;
import java.util.Stack;

/**
 * 完全二叉树的先序,后序,中序  - 递归/循环遍历
 * */
public class TreeConverter {
	// //========递归
	// 递归遍历,先序遍历
	public static void readTreeByRecursionFirst(TreeNode root,
			Queue<TreeNode> to) {
		if (to == null) {
			exception();
		}
		if (root == null) {
			return;
		}
		to.offer(root);
		readTreeByRecursionFirst(root.left, to);
		readTreeByRecursionFirst(root.right, to);
	}

	// 递归遍历,中序遍历
	public static void readTreeByRecursionMiddle(TreeNode root,
			Queue<TreeNode> to) {
		if (to == null) {
			exception();
		}
		if (root == null) {
			return;
		}
		readTreeByRecursionMiddle(root.left, to);
		to.offer(root);
		readTreeByRecursionMiddle(root.right, to);
	}

	// 递归遍历,后序遍历
	public static void readTreeByRecursionEnd(TreeNode root, Queue<TreeNode> to) {
		if (to == null) {
			exception();
		}
		if (root == null) {
			return;
		}
		readTreeByRecursionEnd(root.left, to);
		readTreeByRecursionEnd(root.right, to);
		to.offer(root);
	}

	// 对于错误的参数,直接抛异常,让调用者知道
	private static void exception() {
		throw new RuntimeException("queue can not be null ");
	}
}

3.测试类

package com.aii.algorithm;

import java.util.LinkedList;
import java.util.Queue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TreeConverterTest {
	private TreeNode root = new TreeNode(10);

	private Queue<TreeNode> container = new LinkedList<TreeNode>();

	// ----10
	// ---↓--↓
	// ---6--14
	// --↓-↓-↓-↓
	// --4-8-12-16
	@Before
	public void init() {
		TreeNode t7 = new TreeNode(16);
		TreeNode t6 = new TreeNode(12);
		TreeNode t5 = new TreeNode(8);
		TreeNode t4 = new TreeNode(4);
		TreeNode t3 = new TreeNode(14);
		TreeNode t2 = new TreeNode(6);

		root.left = t2;
		root.right = t3;

		t2.left = t4;
		t2.right = t5;

		t3.left = t6;
		t3.right = t7;

	}

	// /递归
	@Test
	public void testReadTreeByRecursionFirst() {
		TreeConverter.readTreeByRecursionFirst(root, container);
	}

	@Test
	public void testReadTreeByRecursionMiddle() {
		TreeConverter.readTreeByRecursionMiddle(root, container);
	}

	@Test
	public void testReadTreeByRecursionEnd() {
		TreeConverter.readTreeByRecursionEnd(root, container);
	}

	@After
	public void print() {
		System.out.println("result:" + container);
	}

}

正确的结果是:

先序:10-6-4-8-14-12-16

中序:4-6-8-10-12-14-16

后序:4-8-6-12-16-14-10

四、总结

递归遍历非常简单,只要搞清楚当前节点要做什么,把其他的任务扔给其他的节点,调用自己本身这个方法就行了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值