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

原文地址:https://www.cnblogs.com/wangpan8721/p/13693239.html