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

来源:互联网 发布:私有云 软件 编辑:程序博客网 时间:2024/06/06 18:42

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

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

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


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


一、预备知识

树的遍历方式:

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;@Overridepublic 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@Beforepublic 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;}// /////////////////递归@Testpublic void testReadTreeByRecursionFirst() {TreeConverter.readTreeByRecursionFirst(root, container);}@Testpublic void testReadTreeByRecursionMiddle() {TreeConverter.readTreeByRecursionMiddle(root, container);}@Testpublic void testReadTreeByRecursionEnd() {TreeConverter.readTreeByRecursionEnd(root, container);}@Afterpublic 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
原创粉丝点击