java-二叉树遍历
1,完全二叉树-建树,先建简单的树,用简单的树学习各种遍历
2,根据先中序建树,根据中后序建树
1 //先简单建树-按完全二叉树节点插入顺序建树,即层序遍历。2
3 /**二叉树:每个节点最多两个孩子节点(计划生育-最多生二胎);
4 * 完全二叉树(遏制人口老龄化:必须生两胎,否则不准后代传宗接代):
5 * 根节点(爷爷)先生,生不满两胎接着生,爷爷生完,老大(左爸爸)生,
6 * 生不满二胎,爷爷的小儿子不准生,。。。依次类推。
7 * */
8
9 /**按层间遍历顺序加入节点
10 层序遍历用队列,根节点入队,
11 执行循环,当队列不为空{对首X出队,若X左孩子非空,入队,右孩子非空入队}
12 */
13
14 /**层序遍历(用队列先进先出性能实①现先访问根节点(第一层)
15 ②再依次访问根节点的左右孩子节点(第二层)
16 ③再依次访问根节点左右孩子节点的左右孙子节点(第三层),
17 ④.....
18 */
19
20 /**?
21 * 功能
22 * ①,建树--体会完全二叉树,添加节点过程(先建简单的,主要还是体会各种遍历)
23 * ②,4种遍历,7种方法,前、中、后序递归遍历,前、中、后非递归遍历,层序遍历。
24 * ③,删树,
25 * ④,求树高
26 * ⑤,树状打印
27 * ⑥,
28 */
29
30 import java.util.Arrays;
31 import java.util.LinkedList;
32 import java.util.Queue;
33 import java.util.Stack;
34
35 public class Easy_BiTree {
36 //内部Node类
37 public class Node {
38 private int data=Integer.MAX_VALUE;
39 private Node lchild=null;
40 private Node rchild=null;
41
42 public Node(){}
43 public Node(int data){
44 this.data=data;
45 }
46 }
47
48 private Node root=null;
49 private int size=0;
50 public Easy_BiTree(){}
51
52 //添加节点
53 public void addNode(Node root,int data){
54 //根节点
55 if(size==0){
56 this.root=new Node(data);
57 size++;
58 }else{
59 Node newNode=new Node(data);
60
61 // 添加节点用层序遍历方法目的不是为了遍历每一个节点,而是按层次顺序找到第一个孩子不满(没生二胎)的节点
62 // 当遇到孩子节点没满的Node,添加节点-退出;
63 Queue<Node> queue=new LinkedList<>();
64 queue.add(root);
65 while(!queue.isEmpty()){
66 Node curroot=queue.poll();
67 if(curroot.lchild!=null)
68 queue.add(curroot.lchild);
69 else{
70 curroot.lchild=newNode;
71 size++;
72 return;
73 }
74 if(curroot.rchild!=null)
75 queue.add(curroot.rchild);
76 else{
77 curroot.rchild=newNode;
78 size++;
79 return;
80 }
81 }
82 }
83 }
84
85 //遍历-前序非递归,
86
87 /**
88 * ①顺着根节点的左孩子一路到底,一边输出一边入栈,
89 * ②到底后,判断栈顶有没有右子树,有以右子节点为根节点重复①,没有则出栈,
90 */
91 public void preOrder(Node root){
92 if(size==0)
93 System.out.println("树空无遍历");
94 else{
95 System.out.print("树前序非递归: ");
96 Stack<Node> stack=new Stack<>();
97 while(root!=null||!stack.isEmpty()){
98 while(root!=null){
99 System.out.print(root.data+" ");
100 stack.add(root);
101 root=root.lchild;
102 }
103 if(!stack.isEmpty()){
104 root=stack.pop();
105 root=root.rchild;
106 }
107 }
108 System.out.println();
109 }
110 }
111 //遍历-中序非递归,
112 public void inOrder(Node root){
113 if(size==0)
114 System.out.println("树空,无遍历");
115 else {
116 System.out.print("树中序非递归: ");
117 Stack<Node> stack=new Stack<>();
118 while(root!=null||!stack.isEmpty()){
119 while(root!=null){
120 stack.add(root);
121 root=root.lchild;
122 }
123 if(!stack.isEmpty()){
124 root=stack.pop();
125 System.out.print(root.data+" ");
126 root=root.rchild;
127 }
128 }
129 System.out.println();
130 }
131 }
132 //遍历-后序非递归,
133 /**
134 *①顺着根节点的左孩子一路到底,入栈,
135 * ②到底后,判断栈顶有没有右子树,没有出栈,输出
136 * ③有右子节点,右子节点遍历之前不能出栈,preNode,即标识右子节点有没有遍历,
137 * 以右子节点为根节点重复①,②③
138 */
139 public void postOrder(Node root){
140 if(size==0)
141 System.out.println("树空,无遍历");
142 else {
143 System.out.print("树后序非递归: ");
144 Stack<Node> stack=new Stack<>();
145 while(root!=null||!stack.isEmpty()){
146 while(root!=null){
147 stack.push(root);
148 root=root.lchild;
149 }
150 boolean tag=true;
151 Node preNode=null;
152 while(!stack.isEmpty()&&tag==true){
153 root=stack.peek();
154 if(root.rchild==preNode){
155 root=stack.pop();
156 System.out.print(root.data+" ");
157 if(stack.isEmpty()){
158 System.out.println();
159 return;
160 }
161 else
162 preNode=root;
163 }else{
164 root=root.rchild;
165 tag=false;
166 }
167 }
168 }
169 System.out.println();
170 }
171 }
172
173 /**
174 * 额。。递归写起来是很简单,我也说不好原理,233
175 */
176 //遍历-前序递归,
177 public void preOrderRec(Node root){
178 if(root==null)
179 return;
180 else {
181 System.out.print(root.data+" ");
182 preOrderRec(root.lchild);
183 preOrderRec(root.rchild);
184 }
185 }
186 //遍历-中序递归,
187 public void inOrderRec(Node root){
188 if(root==null)
189 return;
190 else{
191 inOrderRec(root.lchild);
192 System.out.print(root.data+" ");
193 inOrderRec(root.rchild);
194 }
195 }
196 //遍历-后序递归,
197 public void postOrderRec(Node root){
198 if(root==null)
199 return;
200 else{
201 postOrderRec(root.lchild);
202 postOrderRec(root.rchild);
203 System.out.print(root.data+" ");
204 }
205 }
206
207
208
209 //遍历,-层间遍历
210 public void levelOrder(Node root){
211 if(this.size==0)
212 System.out.println("空树,无法遍历");
213 else{
214 System.out.println("树层间遍历:");
215 Queue<Node> queue=new LinkedList<>();
216 queue.add(root);
217 while(!queue.isEmpty()){
218 Node curroot=queue.poll();
219 System.out.print(curroot.data+" ");
220 if(curroot.lchild!=null)
221 queue.add(curroot.lchild);
222 if(curroot.rchild!=null)
223 queue.add(curroot.rchild);
224 }
225 System.out.println();
226 }
227 }
228
229 //删树
230 //java有内存回收机制,只要把根节点状态,换成空树根节点状态即可;
231 //C++也是类似遍历一遍,把遍历到的每一个节点free;
232
233 //呃。。。。我猜的,哈哈哈哈哈哈哈哈
234 public void deleteTree(){
235 this.root=null;
236 size=0;
237 }
238
239 /**
240 * 树高-递归和非递归方法
241 * 完全二叉树,节点和高有方程,log(size)向下取整+1
242 * 这里用非特殊二叉树求树高,
243 */
244
245 //转载:https://blog.csdn.net/shijie97/article/details/79775399
246 /**非递归-队列,
247 * 根节点入队,出队,添加第二层,添加完后记录队size(0/1/2),然后将(0/1/2)个出队,将他们的孩子入队,记录每一层
248 * 孩子数,遍历完,即可知道层数
249 */
250 public int treeHeight(Node root){
251 if(root==null)
252 return 0;
253 else if(size==1)
254 return 1;
255 else{
256 Queue<Node> queue=new LinkedList<>();
257 queue.add(root);
258 int height=0;
259 //记录每层孩子个数,root入队长为1
260 int len=1;
261 while(!queue.isEmpty()){
262 int length=0;
263 for(int i=0;i<len;i++){
264 Node curroot=queue.poll();
265 if(curroot.lchild!=null){
266 queue.add(curroot.lchild);
267 length++;
268 }
269 if(curroot.rchild!=null){
270 queue.add(curroot.rchild);
271 length++;
272 }
273 }
274 len=length;
275 height++;
276 }
277 return height;
278 }
279 }
280 //递归
281 public int treeHeightRec(Node root){
282 if(root==null)
283 return 0;
284 else{
285 int a =treeHeightRec(root.lchild);
286 int b = treeHeightRec(root.rchild);
287 return (a>b)?(a+1):(b+1);
288 }
289 }
290
291 //树状打印
292 /**
293 * 思路:先确定树高h-最后一层2^(h-1)个数,好知道根节点放在哪里(预留空间保证根再中间)
294 * 设每个data三位数=space,元素之间空三位数,每行 (2^H+1)*3 个“ ”
295 * _数_数_数_数_数_ 每层2^(h-1)个数,2^(h-1)+1个space,最后一行长2^h+1个space
296 *
297 * 当层数多的时候稍乱,2333不想弄了,
298 */
299 public void printTree(Node root){
300 int H=treeHeight(root);
301 int h=H;
302 //System.out.println("树高:"+H);
303 if(H==0)
304 System.out.println("树空,无打印");
305 else{
306 System.out.println("打印树:");
307 Queue<Node> queue=new LinkedList<>();
308 queue.add(root);
309 int height=1;
310 //记录每层孩子个数
311 int len=1;
312 while(h>0){
313 int length=0;
314 String space="";
315 for(int i=0;i<(((Math.pow(2,H)+1)*3)/(Math.pow(2,height)+1));i++)
316 space+=" ";
317 for(int i=0;i<len;i++){
318 Node curroot=queue.poll();
319 if(curroot.data==Integer.MAX_VALUE){
320 System.out.print(space);
321 }else
322 System.out.print(space+curroot.data);
323
324 if(curroot.lchild!=null){
325 queue.add(curroot.lchild);
326 }
327 else
328 queue.add(new Node());
329 length++;
330 if(curroot.rchild!=null){
331 queue.add(curroot.rchild);
332 }
333 else
334 queue.add(new Node());
335 length++;
336 }
337 System.out.println();
338 System.out.println();
339 len=length;
340 height++;
341 h--;
342 }
343 System.out.println();
344 }
345 }
346
347
348 /**
349 *
350 * 根据先序和中序创建二叉树
351 * 转载:https://www.cnblogs.com/tuyang1129/p/11647443.html
352 * ①先序的第一个元素为根节点,②找出这个根节点在中序中的位置x,xx左边是根节点的左子树,右边是右子树
353 * ③递归建树
354 *
355 */
356
357 public int getIndex(int data,int[] array){
358 int num =Integer.MAX_VALUE;
359 for(int i=0;i<array.length;i++){
360 if(array[i]==data)
361 num=i;
362 }
363 return num;
364 }
365
366 public Node preIn_BiTree(int[] pre,int[] in){
367 if(pre.length==0){
368 return null;
369 }else if(pre.length==1){
370 return new Node(pre[0]);
371 }
372 Node root=new Node(pre[0]);
373
374 int index=getIndex(pre[0],in);
375
376 //左子树
377 int[] preleft= Arrays.copyOfRange(pre,1,index+1);
378 int[] inleft=Arrays.copyOfRange(in,0,index);
379 root.lchild=preIn_BiTree(preleft,inleft);
380
381 //右子树
382 int[] preright=Arrays.copyOfRange(pre,index+1,pre.length);
383 int[] inright=Arrays.copyOfRange(in,index+1,in.length);
384 root.rchild=preIn_BiTree(preright,inright);
385
386 return root;
387
388 }
389
390 /**
391 * 根据中序-后续
392 * ①后序的第一个元素为根节点,②找出这个根节点在中序中的位置x,x左边是根节点的左子树,右边是右子树
393 * ③递归建树
394 */
395 public Node inPost_BiTree(int[] in,int[] post){
396 if(in.length==0){
397 return null;
398 }else if(in.length==1){
399 return new Node(in[0]);
400 }
401 Node root=new Node(post[post.length-1]);
402 int index=getIndex(post[post.length-1],in);
403
404 //左子树
405 int[] postleft= Arrays.copyOfRange(post,0,index);
406 int[] inleft=Arrays.copyOfRange(in,0,index);
407 root.lchild=inPost_BiTree(inleft,postleft);
408
409 //右子树
410 int[] postright=Arrays.copyOfRange(post,index,post.length-1);
411 int[] inright=Arrays.copyOfRange(in,index+1,in.length);
412 root.rchild=inPost_BiTree(inright,postright);
413
414 return root;
415
416 }
417
418
419
420
421 public static void main(String args[]) {
422 /**
423 * 完全二叉树的建立,与二叉树的遍历
424 */
425 Easy_BiTree t=new Easy_BiTree();
426 t.addNode(t.root,1);
427 t.addNode(t.root,2);
428 t.addNode(t.root,3);
429 t.addNode(t.root,4);
430 t.addNode(t.root,5);
431 t.addNode(t.root,6);
432 t.addNode(t.root,7);
433 t.addNode(t.root,8);
434 t.addNode(t.root,9);
435 t.addNode(t.root,10);
436 t.addNode(t.root,11);
437 t.addNode(t.root,12);
438 t.addNode(t.root,13);
439 t.addNode(t.root,14);
440 t.addNode(t.root,15);
441 t.addNode(t.root,16);
442 t.addNode(t.root,17);
443 t.addNode(t.root,18);
444 t.addNode(t.root,19);
445 t.addNode(t.root,20);
446 t.addNode(t.root,21);
447
448 t.levelOrder(t.root);
449 System.out.println("非递归求树高: "+t.treeHeight(t.root));
450 System.out.println("递归求树高: "+t.treeHeightRec(t.root));
451
452 t.printTree(t.root);
453
454 t.preOrder(t.root);
455 t.inOrder(t.root);
456 t.postOrder(t.root);
457
458 System.out.print("树前序递归遍历: ");
459 t.preOrderRec(t.root);
460 System.out.println();
461 System.out.print("树中序递归遍历: ");
462 t.inOrderRec(t.root);
463 System.out.println();
464 System.out.print("树后序递归遍历: ");
465 t.postOrderRec(t.root);
466 System.out.println();
467
468 t.deleteTree();
469 System.out.println("非递归求树高: "+t.treeHeight(t.root));
470
471
472 /**
473 * 其他建树方法
474 */
475 int[] pre={1,2,4,7,3,5,6};
476 int[] in={2,7,4,1,5,3,6};
477 int[] post={7,4,2,5,6,3,1};
478
479 int[] pre1={1,2,3,4,5,6,7};
480 int[] in1={2,4,6,7,5,3,1};
481 int[] post1={7,6,5,4,3,2,1};
482
483
484 System.out.println("pre={1,2,4,7,3,5,6}");
485 System.out.println("in={2,7,4,1,5,3,6}");
486 Easy_BiTree t2=new Easy_BiTree();
487 t2.root=t2.preIn_BiTree(pre,in);
488 t2.printTree(t2.root);
489
490 System.out.println("pre1={1,2,3,4,5,6,7}");
491 System.out.println("in1={2,4,6,7,5,3,1}");
492 Easy_BiTree t3=new Easy_BiTree();
493 t3.root=t3.preIn_BiTree(pre1,in1);
494 t3.printTree(t3.root);
495
496 System.out.println("in={2,7,4,1,5,3,6}");
497 System.out.println("post={7,4,2,5,6,3,1}");
498 Easy_BiTree t4=new Easy_BiTree();
499 t4.root=t4.inPost_BiTree(in,post);
500 t4.printTree(t4.root);
501
502 System.out.println("in1={2,7,4,1,5,3,6}");
503 System.out.println("post1={7,4,2,5,6,3,1}");
504 Easy_BiTree t5=new Easy_BiTree();
505 t5.root=t5.inPost_BiTree(in1,post1);
506 t5.printTree(t5.root);
507
508 }
509 }
View Code
以上是 java-二叉树遍历 的全部内容, 来源链接: utcz.com/z/390697.html