码迷,mamicode.com
首页 > 其他好文 > 详细

树的递归与非递归遍历总结

时间:2014-07-25 19:04:32      阅读:317      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   os   strong   io   

  树的递归遍历遍历很简单,非递归遍历要复杂一些,非递归先序、中序、后序遍历需要用一个辅助栈,而层次遍历则需要一个辅助队列。

  树的结构 

1 public class Tree<T> {
2     private T data;
3     private Tree<T> left;
4     private Tree<T> right;
5         ...
6 }

   用策略模式定义一个访问工具: 

1 public interface Visitor<T> {
2         void process(T data);
3     }

  先上递归访问方法:

 1    /**
 2      * 递归中序遍历
 3      * 
 4      * @param visitor
 5      */
 6     public void recursionInOrder(Visitor<T> visitor) {
 7         if (left != null)// 如果左子树存在,先访问左子树
 8             left.recursionInOrder(visitor);
 9         visitor.process(data);// 访问当前结点
10         if (right != null)// 如果右子树存在,访问右子树
11             right.recursionInOrder(visitor);
12     }
13 
14     /**
15      * 递归先序遍历
16      * 
17      * @param visitor
18      */
19     public void recursionPreOrder(Visitor<T> visitor) {
20         visitor.process(data);// 访问当前结点
21         if (left != null)// 如果左子树存在,访问左子树
22             left.recursionPreOrder(visitor);
23         if (right != null)// 如果右子树存在,访问右子树
24             right.recursionPreOrder(visitor);
25     }
26 
27     /**
28      * 递归后序遍历
29      * 
30      * @param visitor
31      */
32     public void recursionPostOrder(Visitor<T> visitor) {
33         if (left != null)// 如果左子树存在,先访问左子树
34             left.recursionInOrder(visitor);
35         if (right != null)// 如果右子树存在,访问右子树
36             right.recursionInOrder(visitor);
37         visitor.process(data);// 访问当前结点
38     }

  层次遍历,使用一个辅助队列,以便逐层访问:  

 1     /**
 2      * 层次遍历
 3      * 
 4      * @param visitor
 5      */
 6     public void levelViste(Visitor<T> visitor) {
 7         Queue<Tree<T>> queue = new LinkedList<Tree<T>>();
 8         queue.add(this);
 9         while (!queue.isEmpty()) {
10             Tree<T> node = queue.poll();
11             visitor.process(node.data);
12             if (node.left != null)
13                 queue.add(node.left);
14             if (node.right != null)
15                 queue.add(node.right);
16         }
17     }

  非递归的先序与中序遍历差别很小,唯一不同之处是先序在把结点放入栈前就访问了,而中序是在结点出栈的时候访问。

 1 /**
 2      * 先序遍历
 3      * 
 4      * @param visitor
 5      */
 6     public void preOrderViste(Visitor<T> visitor) {
 7         Stack<Tree<T>> stack = new Stack<Tree<T>>();
 8         Tree<T> node = this;
 9         while (node != null || !stack.isEmpty()) {
10             if (node != null) {// 向左走到尽头
11                 visitor.process(node.data);
12                 stack.add(node);
13                 node = node.left;
14             } else {
15                 node = stack.pop();
16                 node = node.right;
17             }
18         }
19     }
20 
21     /**
22      * 中序遍历
23      * 
24      * @param visitor
25      */
26     public void inOrderViste(Visitor<T> visitor) {
27 
28         Stack<Tree<T>> stack = new Stack<Tree<T>>();
29         Tree<T> node = this;
30         while (node != null || !stack.isEmpty()) {
31             if (node != null) {// 向左走到尽头
32                 stack.add(node);
33                 node = node.left;
34             } else {
35                 node = stack.pop();
36                 visitor.process(node.data);
37                 node = node.right;
38             }
39 
40         }
41     }

  后续遍历略微复杂一些,因为根结点要最后访问,需要知道回溯是来自左孩子还是右孩子,因此需要记录上一次访问的结点。

 1   /**
 2      * 后续遍历
 3      * 
 4      * @param visitor
 5      */
 6     public void postOrderViste(Visitor<T> visitor) {
 7         Stack<Tree<T>> stack = new Stack<Tree<T>>();
 8         Tree<T> node = this, last = null;
 9         while (node != null || !stack.isEmpty()) {
10             if (node != null) {// 向左走到尽头
11                 stack.add(node);
12                 node = node.left;
13             } else {
14                 node = stack.peek();
15                 if (node.right != null && node.right != last) {// 有右孩子
16                     node = node.right;// 向右走一步
17                     stack.add(node);
18                     node = node.left;// 向左走到尽头
19                 } else {// 访问结点
20                     node = stack.pop();
21                     visitor.process(node.data);
22                     last = node;
23                     node = null;// 置为空,强制去探索右孩子
24                 }
25             }
26         }
27     }

  测试:

 1 private static Visitor<Integer> visitor = new Visitor<Integer>() {
 2         @Override
 3         public void process(Integer data) {
 4             System.out.print(data + " ");
 5         }
 6     };
 7 
 8     /**
 9      * 根据方法名测试访问
10      * 
11      * @param tree
12      * @param method
13      * @param visitor
14      * @throws Exception
15      */
16     private static void test(Tree<?> tree, String method, Visitor<?> visitor)
17             throws Exception {
18         Class<?> c = (Class<?>) Class.forName("tree.Tree");
19         Method func = c.getDeclaredMethod(method, Visitor.class);
20         func.invoke(tree, visitor);
21         System.out.println("(" + method + ")");
22 
23     }
24 
25     public static void main(String[] args) throws Exception {
26         Integer[] datas = { 0, 1, 2, 3, 4, 5, 6, 7 };
27         Tree<Integer> tree = new Tree<Integer>(datas);
28         test(tree, "preOrderViste", visitor);
29         test(tree, "inOrderViste", visitor);
30         test(tree, "postOrderViste", visitor);
31         test(tree, "inOrderViste", visitor);
32         test(tree, "recursionInOrder", visitor);
33         test(tree, "recursionPreOrder", visitor);
34         test(tree, "recursionPostOrder", visitor);
35         test(tree, "levelViste", visitor);
36     }

  完整的代码折叠起来了:

bubuko.com,布布扣
  1 public class Tree<T> {
  2     private T data;
  3     private Tree<T> left;
  4     private Tree<T> right;
  5 
  6     private Tree(T data) {
  7         this.data = data;
  8 
  9     }
 10 
 11     public Tree(T[] datas) {
 12         makeTree(datas, this);
 13     }
 14 
 15     public interface Visitor<T> {
 16         void process(T data);
 17     }
 18 
 19     /**
 20      * 递归中序遍历
 21      * 
 22      * @param visitor
 23      */
 24     public void recursionInOrder(Visitor<T> visitor) {
 25         if (left != null)// 如果左子树存在,先访问左子树
 26             left.recursionInOrder(visitor);
 27         visitor.process(data);// 访问当前结点
 28         if (right != null)// 如果右子树存在,访问右子树
 29             right.recursionInOrder(visitor);
 30     }
 31 
 32     /**
 33      * 递归先序遍历
 34      * 
 35      * @param visitor
 36      */
 37     public void recursionPreOrder(Visitor<T> visitor) {
 38         visitor.process(data);// 访问当前结点
 39         if (left != null)// 如果左子树存在,访问左子树
 40             left.recursionPreOrder(visitor);
 41         if (right != null)// 如果右子树存在,访问右子树
 42             right.recursionPreOrder(visitor);
 43     }
 44 
 45     /**
 46      * 递归后序遍历
 47      * 
 48      * @param visitor
 49      */
 50     public void recursionPostOrder(Visitor<T> visitor) {
 51         if (left != null)// 如果左子树存在,先访问左子树
 52             left.recursionInOrder(visitor);
 53         if (right != null)// 如果右子树存在,访问右子树
 54             right.recursionInOrder(visitor);
 55         visitor.process(data);// 访问当前结点
 56     }
 57 
 58     /**
 59      * 层次遍历
 60      * 
 61      * @param visitor
 62      */
 63     public void levelViste(Visitor<T> visitor) {
 64         Queue<Tree<T>> queue = new LinkedList<Tree<T>>();
 65         queue.add(this);
 66         while (!queue.isEmpty()) {
 67             Tree<T> node = queue.poll();
 68             visitor.process(node.data);
 69             if (node.left != null)
 70                 queue.add(node.left);
 71             if (node.right != null)
 72                 queue.add(node.right);
 73         }
 74     }
 75 
 76     /**
 77      * 先序遍历
 78      * 
 79      * @param visitor
 80      */
 81     public void preOrderViste(Visitor<T> visitor) {
 82         Stack<Tree<T>> stack = new Stack<Tree<T>>();
 83         Tree<T> node = this;
 84         while (node != null || !stack.isEmpty()) {
 85             if (node != null) {// 向左走到尽头
 86                 visitor.process(node.data);
 87                 stack.add(node);
 88                 node = node.left;
 89             } else {
 90                 node = stack.pop();
 91                 node = node.right;
 92             }
 93         }
 94     }
 95 
 96     /**
 97      * 中序遍历
 98      * 
 99      * @param visitor
100      */
101     public void inOrderViste(Visitor<T> visitor) {
102 
103         Stack<Tree<T>> stack = new Stack<Tree<T>>();
104         Tree<T> node = this;
105         while (node != null || !stack.isEmpty()) {
106             if (node != null) {// 向左走到尽头
107                 stack.add(node);
108                 node = node.left;
109             } else {
110                 node = stack.pop();
111                 visitor.process(node.data);
112                 node = node.right;
113             }
114         }
115     }
116 
117     /**
118      * 后续遍历
119      * 
120      * @param visitor
121      */
122     public void postOrderViste(Visitor<T> visitor) {
123         Stack<Tree<T>> stack = new Stack<Tree<T>>();
124         Tree<T> node = this, last = null;
125         while (node != null || !stack.isEmpty()) {
126             if (node != null) {// 向左走到尽头
127                 stack.add(node);
128                 node = node.left;
129             } else {
130                 node = stack.peek();
131                 if (node.right != null && node.right != last) {// 有右孩子
132                     node = node.right;// 向右走一步
133                     stack.add(node);
134                     node = node.left;// 向左走到尽头
135                 } else {// 访问结点
136                     node = stack.pop();
137                     visitor.process(node.data);
138                     last = node;
139                     node = null;// 置为空,强制去探索右孩子
140                 }
141             }
142         }
143     }
144 
145     /**
146      * 构造一个满二叉树
147      * 
148      * @param datas
149      * @param root
150      */
151     public void makeTree(T[] datas, Tree<T> root) {
152         List<Tree<T>> trees = new ArrayList<Tree<T>>(datas.length);
153         root.data = datas[0];
154         trees.add(root);
155         for (int i = 1; i < datas.length; i++) {
156             trees.add(new Tree<T>(datas[i]));
157         }
158         int level = (int) (Math.log(datas.length) / Math.log(2));
159         for (int i = 0; i <= level; i++) {
160             int left = i * 2 + 1;
161             if (left < datas.length)
162                 trees.get(i).left = trees.get(left);
163             int right = i * 2 + 2;
164             if (right < datas.length)
165                 trees.get(i).right = trees.get(right);
166         }
167     }
168 
169     private static Visitor<Integer> visitor = new Visitor<Integer>() {
170         @Override
171         public void process(Integer data) {
172             System.out.print(data + " ");
173         }
174     };
175 
176     /**
177      * 根据方法名测试访问
178      * 
179      * @param tree
180      * @param method
181      * @param visitor
182      * @throws Exception
183      */
184     private static void test(Tree<?> tree, String method, Visitor<?> visitor)
185             throws Exception {
186         Class<?> c = (Class<?>) Class.forName("tree.Tree");
187         Method func = c.getDeclaredMethod(method, Visitor.class);
188         func.invoke(tree, visitor);
189         System.out.println("(" + method + ")");
190 
191     }
192 
193     public static void main(String[] args) throws Exception {
194         Integer[] datas = { 0, 1, 2, 3, 4, 5, 6, 7 };
195         Tree<Integer> tree = new Tree<Integer>(datas);
196         test(tree, "preOrderViste", visitor);
197         test(tree, "inOrderViste", visitor);
198         test(tree, "postOrderViste", visitor);
199         test(tree, "inOrderViste", visitor);
200         test(tree, "recursionInOrder", visitor);
201         test(tree, "recursionPreOrder", visitor);
202         test(tree, "recursionPostOrder", visitor);
203         test(tree, "levelViste", visitor);
204     }
205 }
View Code

  转载请注明出处:http://www.cnblogs.com/fengfenggirl

树的递归与非递归遍历总结,布布扣,bubuko.com

树的递归与非递归遍历总结

标签:style   blog   http   color   使用   os   strong   io   

原文地址:http://www.cnblogs.com/fengfenggirl/p/tree_visite.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!