我们知道,二叉树的搜索分为深度优先搜索和广度优先搜索
深度优先搜索,简单来说就是竖着遍历,分为前序遍历,中序遍历和后序遍历
广度优先搜索,就是横着搜索,因为也叫层序遍历
一、JZ-offer-32(1) 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
层序遍历一般用到队列的概念。利用了队列具有先进先出的特性,
具体实现过程就是:每次弹出一个节点,就判断该节点是否有子节点,有就将其加入到队列中,这样就实现了队列中的元素始终是按层排队的。
function levalOrder(root){
if(root == null) return [];
//定义一个队列
let queue = [root];
//定义一个空的数组,存储节点的值
let res = [];
//终止条件就是队列为空
while(queue.length){
let node = queue.shift();
res.push(node.val);
//判断这个Node 是否有子节点,有就插入到队列尾部
if(node.left) {queue.push(node.left)}
if(node.right) {queue.push(node.right)}
}
return res
}
二、JZ-offer-32(2) 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
与上面的差别是:按层打印,一层打印到一个数组,有几层就打印几个数组,最后再插入到一个数组中
function levelOrder(root){
if(root==null) return [];
let queue = [root];
let res = [];
while(queue.length){
let path = [];
for(let i= queue.length;i>0; i--){
let node = queue.shift();
path.push(node.val)
if(node.left) {queue.push(node.left)}
if(node.right) {queue.push(node.right)}
}
res.push(path)
}
return res
}
注意点:在这个for循环中,用i递减的形式,必须先获取队列的长度,因为队列的长度能随时变化
三、JZ-offer-32(3) 之字形打印二叉树
就是第一行正序打印,第二行逆序打印呗,跟第二题类似,只是需要判断是奇数层还是偶数层。
function levelOrder(root){
if(root == null) return null;
let queue = [root];
let res = [];
while(queue.length){
let path = [];
for(let i=queue.length;i>0;i--){
let node = queue.shift();
//判断是逆序插入还是正序插入--根据此时res的长度判断
if(res.length % 2==0){
path.push(node.val)
}
else{
path.unshift(node.val)
}
if(node.left) {queu.push(node.left)}
if(node.right) {queue.push(node.right)}
}
res.push(path)
}
return res
}