2、二叉树:递归遍历
2016-03-04 18:48 宏愿。 阅读(522) 评论(0) 编辑 收藏 举报
对二叉树而言,最为核心的操作就是遍历。遍历可以用递归的方式,也可以用循环的方式。
就递归遍历而言,又有“先序、中序、后续”三种不同的遍历顺序。通过下面的一个示意图可以从感官上来体会一下三种不同的遍历顺序:
为了学习二叉树的相关算法,首先需要构建一个二叉树的抽象类public abstract class BiTreeAbstract<T> ,该类中有一个表示结点的内部类Node,将结点的数据类型定义为泛型T以方便将其用于不同的数据类型。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.magicode.datastructure.tree; 2 3 public abstract class BiTreeAbstract<T> { 4 /** 5 * 树的根节点。 6 */ 7 private Node root; 8 9 /** 10 * 具体的构建二叉树方法。 如果构建成功,则返回二叉树的根节点(Node); 如果构建失败,则范湖null。 11 * 12 * @return 二叉树的根节点Node 13 */ 14 abstract protected Node initMethod(); 15 16 /** 17 * 访问二叉树中的元素节点。 如果需要终止遍历,则返回false;如果需要继续遍历下去,则返回true。 18 * 19 * @return 20 */ 21 abstract protected boolean visitElem(Node node); 22 23 /** 24 * 创建一个二叉树,在此方法中具体调用抽象方法initMethod来 创建一个二叉树。 25 * 26 * @return 27 */ 28 public boolean createBiTree() { 29 root = initMethod(); 30 if (root != null) { 31 return true; 32 } 33 return false; 34 }; 35 36 /** 37 * 递归的“先序”遍历二叉树</br> 具体会调用抽象方法visitElem来具体处理遍历过程中的元素。 38 * 39 * @return 遍历成功,则返回true。遍历失败,返回false。 40 */ 41 public boolean preOrderTraverse() { 42 return preTraverse(root); 43 } 44 45 private boolean preTraverse(Node node) { 46 if (node == null) { 47 return true; 48 } 49 // 改变下面三条if语句的先后关系,就可以实现“中序”和“后序”递归遍历 50 if (visitElem(node)) 51 if (preTraverse(node.lchild)) 52 if (preTraverse(node.rchild)) 53 return true; 54 return false; 55 } 56 57 public Node getRoot() { 58 return root; 59 } 60 61 /** 62 * 节点结构 63 */ 64 protected class Node { 65 66 private T elem; 67 private Node lchild; 68 private Node rchild; 69 70 public Node() { 71 } 72 73 public Node(T elem) { 74 this.elem = elem; 75 lchild = null; 76 rchild = null; 77 } 78 79 public T getElem() { 80 return elem; 81 } 82 83 public Node getLchild() { 84 return lchild; 85 } 86 87 public Node getRchild() { 88 return rchild; 89 } 90 91 public void setElem(T elem) { 92 this.elem = elem; 93 } 94 95 public void setLchild(Node lchild) { 96 this.lchild = lchild; 97 } 98 99 public void setRchild(Node rchild) { 100 this.rchild = rchild; 101 } 102 103 } 104 105 }
抽象类中定义了两个功能方法:
①、public boolean createBiTree()用于构建一个二叉树,在该方法中会调用abstract protected Node initMethod()方法来具体的对构建二叉树;
②、public boolean preOrderTraverse()方法的功能是先序递归的方法来遍历二叉树,它会调用抽象方法abstract protected boolean visitElem(Node node)在遍历过程对访问的当前节点进行处理,如果想在某个结点处终止遍历,只需要在visitElem方法中返回一个false即可。
下面是一个具体的实现类,它会构建一个满二叉树:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.magicode.datastructure.tree; 2 3 public class BiTree extends BiTreeAbstract<Integer> { 4 5 private int n = 0; 6 private String[] dat = "1|2|3|4|0|0|5|0|0|6|7|0|0|8|0|0|9|10|11|0|0|12|0|0|13|14|0|0|15|0|0".split("\\|"); 7 8 private Node create(String[] str) { 9 Integer ele = Integer.parseInt(str[n]); 10 n++; 11 //0表示该孩子节点为null 12 if(ele == 0){ 13 return null; 14 } 15 Node nod = new Node(ele); 16 //先构建左孩子,后构建右孩子。构建顺序于先序遍历是一致的。 17 nod.setLchild(create(str)); 18 nod.setRchild(create(str)); 19 return nod; 20 } 21 22 @Override 23 protected Node initMethod() { 24 Node nd = create(dat); 25 return nd; 26 } 27 28 @Override 29 protected boolean visitElem(Node node) { 30 System.out.print(node.getElem() + " "); 31 return true; 32 } 33 34 public static void main(String[] args) { 35 BiTree tree = new BiTree(); 36 System.out.println(tree.createBiTree()); 37 38 System.out.println(); 39 System.out.println("--------先序遍历------"); 40 tree.preOrderTraverse(); 41 42 } 43 44 }
运行测试结果(中序和后序只需要依据代码说明进行修改即可实现):