按之字形顺序打印二叉树

按之字形顺序打印二叉树

一、总结

1、一行一行打印用的队列做BFS(广度优先搜索)

2、这里因为要区分奇偶行,用了两个队列。

3、效率的保障用的是奇数行存的时候是从左向右存入队列,偶数行的时候是从右向左存。而不是偶数行节点也会从左向右存入队列,然后array_reverse(),大量数据的时候这样效率很低的。

二、题目描述

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
 
 

三、代码

代码一:java

 1 /**
 2  * 大家的实现很多都是将每层的数据存进ArrayList中,偶数层时进行reverse操作,
 3  * 在海量数据时,这样效率太低了。
 4  * (我有一次面试,算法考的就是之字形打印二叉树,用了reverse,
 5  * 直接被鄙视了,面试官说海量数据时效率根本就不行。)
 6  *
 7  * 下面的实现:不必将每层的数据存进ArrayList中,偶数层时进行reverse操作,直接按打印顺序存入
 8  * 思路:利用Java中的LinkedList的底层实现是双向链表的特点。
 9  *     1)可用做队列,实现树的层次遍历
10  *     2)可双向遍历,奇数层时从前向后遍历,偶数层时从后向前遍历
11  */
12 public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
13     ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
14     if (pRoot == null) {
15         return ret;
16     }
17     ArrayList<Integer> list = new ArrayList<>();
18     LinkedList<TreeNode> queue = new LinkedList<>();
19     queue.addLast(null);//层分隔符
20     queue.addLast(pRoot);
21     boolean leftToRight = true;
22      
23     while (queue.size() != 1) {
24         TreeNode node = queue.removeFirst();
25         if (node == null) {//到达层分隔符
26             Iterator<TreeNode> iter = null;
27             if (leftToRight) {
28                 iter = queue.iterator();//从前往后遍历
29             } else {
30                 iter = queue.descendingIterator();//从后往前遍历
31             }
32             leftToRight = !leftToRight;
33             while (iter.hasNext()) {
34                 TreeNode temp = (TreeNode)iter.next();
35                 list.add(temp.val);
36             }
37             ret.add(new ArrayList<Integer>(list));
38             list.clear();
39             queue.addLast(null);//添加层分隔符
40             continue;//一定要continue
41         }
42         if (node.left != null) {
43             queue.addLast(node.left);
44         }
45         if (node.right != null) {
46             queue.addLast(node.right);
47         }
48     }
49      
50     return ret;
51 }

代码二:php

 1 <?php
 2  
 3 /*class TreeNode{
 4     var $val;
 5     var $left = NULL;
 6     var $right = NULL;
 7     function __construct($val){
 8         $this->val = $val;
 9     }
10 }*/
11 function MyPrint($pRoot)
12 {
13     if($pRoot == NULL)
14         return [];
15     $current = 0;  //记录当前行是奇数行还是偶数行
16     $next    = 1;
17      
18     $stack[0] = array();
19     $stack[1] = array();
20     $resultQueue = array();
21      
22     array_push($stack[0], $pRoot);
23      
24     $i = 0; //记录达到数的第多少层
25     $result = array();
26     $result[0]= array();
27      
28     while(!empty($stack[0]) || !empty($stack[1])){
29         $node = array_pop($stack[$current]);
30         array_push($result[$i], $node->val);
31          
32         //var_dump($resultQueue);echo "</br>";
33         if($current == 0){ //如果当前为奇数行,从左到右存入节点
34             if($node->left != NULL)
35                 array_push($stack[$next], $node->left);
36             if($node->right != NULL)
37                 array_push($stack[$next], $node->right);
38         }else{ //当前为偶数行,从右向左存入节点
39             if($node->right != NULL)
40                 array_push($stack[$next], $node->right);
41             if($node->left != NULL)
42                 array_push($stack[$next], $node->left);
43         }
44          
45         if(empty($stack[$current])){ //打印完一行之后
46             $current = 1-$current;
47             $next    = 1-$next;
48             if(!empty($stack[0]) || !empty($stack[1])){
49                 $i++;
50                 $result[$i] = array();
51             }
52         }
53          
54     }
55     return $result;
56      
57 }

四、测试题-简答题

1、php中类中的构造器的函数名是怎么写?

解答:function __construct($val){}

2、php中如何判断一个链表节点是否为空?

解答:if($pRoot == NULL)

3、php中如何返回一个空数组?

解答:return [];

4、之字形输出树的题目中,队列里面存节点还是值,答案数组里面存节点还是值?

解答:队列里面存节点,答案数组里面存值。

5、如何实现奇偶行切换?

解答:$current = 0; //记录当前行是奇数行还是偶数行  $current = 1-$current;

6、之字形输出树的题目中,如何判断树到达了下一层?

解答:当前队列打印完之后。if(empty($stack[$current]))

7、之字形输出树的题目中,答案数组继续加行的前提是什么?

解答:奇数行队列或者偶数行队列至少有一个还有值。也就是非空。if(!empty($stack[0]) || !empty($stack[1]))

8、php中如何判断一个数组非空?

解答:用!empty()。if(!empty($stack[0]) || !empty($stack[1]))

9、之字形输出树的题目中,要保证奇偶行操作方式不同,需要几个队列?

解答:两个。

10、之字形输出树的题目中,如何提高效率?

解答:奇数行队列从左向右存,偶数行队列从右向左存。

11、树的层次遍历,用的是什么数据结构?

解答:队列。

12、队列数据结构的操作核心是?

解答:判断队列是否有值,有值的话就做入队或出队操作。

 
 
 
原文地址:https://www.cnblogs.com/Renyi-Fan/p/9112654.html