给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
来源:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
基本思路:这里通过队列实现迭代来实现的
1、定义一个队列,用于存放节点
2、判断队列是否为空,如果不为空,那么首先获取当前队列中的节点个数,然后再就从队列中跳出一个节点,然后通过判断这个节点左右子节点是否为null,从而可以知道是否要将它的左右子节点压入队列中,但是值得注意的是,必须要获取当前队列中的节点个数,从而可以知道每从队列中跳出一个节点时,往集合中添加的节点之前有多少个节点
3、重复步骤2,直到队列为空
节点类:
public class Node {
public int value;
public Node left;
public Node right;
public Node(int value){
this.value = value;
}
@Override
public String toString() {
return value+" ";
}
}
测试类:
/**
* 二叉树的层序遍历(即从左到右进行输出,并且逐层访问
* 基本思路:通过队列实现迭代,从而实现二叉树的层序遍历
* 1、将根节点压入到队列中
* 2、之后,将从队列中跳出一个节点,并且判断这个新跳出节点的左右子节点是否为空,如果为空,就不要
* 将其压入到队列中去,否则就将其压入队列中
* 3、重复2操作,知道队列为空
*/
public class TreeCenXuDisplay {
public static List<List<Integer>> list = new ArrayList<>();
public int[] arr = {4,5,8,10,12,15,18};//通过中序遍历得到的数组来构建二叉树
public static void main(String[] args) {
TreeCenXuDisplay test = new TreeCenXuDisplay();
Node root = test.buildTree(0,test.arr.length);
System.out.print("通过中序遍历得到的二叉树的前序遍历: ");
test.display(root);
System.out.println();
System.out.println("二叉树的层序遍历: ");
test.display2(root);
for (List<Integer> list2: list) {
System.out.println(list2);
}
}
/**
* 将一个按照升序排列的有序数组(即二叉树中序遍历得到的),转换为一棵高度平衡二叉搜索树。
*本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
* @param start
* @param end
*/
public Node buildTree(int start, int end) {
if(start >= end){
/**
* 如果范围不正确的时候,结束递归,注意这里必须要有=,因为end一开始传递的参数时数组的长度,此时
* end - start表示的是数组的长度,此时如果start = end是,表示的是有0个元素,所以结束递归,
* start > end就更不用说了
*/
return null;
}
int mid = (start + end) / 2;//数组中间或者中间偏一个节点是根节点
Node root = new Node(arr[mid]);//新建一个根节点
//构建左子树、右子树
root.left = buildTree(start,mid);
root.right = buildTree(mid + 1,end);
return root;
}
/**
* 树的前序遍历
*/
public void display(Node root) {
if(root == null){
return;
}
System.out.print(root + " ");
display(root.left);
display(root.right);
}
/**
* 树的层序遍历:通过一个队列实现迭代,从而实现层序遍历
* 基本思路:
* 1、定义一个队列,用于存放节点
* 2、判断队列是否为空,如果不为空,那么首先获取当前队列中的节点个数,然后再就从队列中跳出一个节点,然后通过判断这个
* 节点左右子节点是否为null,从而可以知道是否要将它的左右子节点压入队列中,但是值得注意的是,必须要获取当前队列中的节点个数,从而可以知道每从队列中跳出一个节点时,往集合中添加的节点有多少个
* 3、重复步骤2,知道队列为空
*/
public void display2(Node root){
//定义一个队列
Queue<Node> queue = new LinkedList<>();
//定义一个集合
ArrayList<Integer> arrayList = null;
//将根节点添加到队列中
queue.offer(root);
//通过判断队列是否为空,从而将其左右子节点添加到队列中
while(!queue.isEmpty()){
arrayList = new ArrayList<>();
//获取当前队列中的节点个数
int size = queue.size();
for (int i = 0; i < size; i++) {
//注意的是,这里的循环条件不可以时queue.size,否则就会发生报错
//将队列中跳出一个根节点,并将其对应的值添加到集合arrayList中
root = queue.poll();
arrayList.add(root.value);
//判断当前根节点的左右子节点是否为空,如果不为空,就添加到队列中
if(root.left != null){
queue.offer(root.left);
}
if(root.right != null){
queue.offer(root.right);
}
}
list.add(arrayList);//将一个集合添加到list中
}
}
}
运算结果:
值得注意的是,构造层序遍历的代码不可以是这样子的,即不可以是单层循环:
/**
* 这里没有直到每一层中的节点个数,并且只是单层循环,那么每一次只能向队列中添加两个节点
* 所以需要有嵌套循环,并且第二层循环的循环条件是要直到每一层中节点个数,即队列的节点个数
* @param root
*/
private void display3(Node root) {
//新建一个队列
Queue<Node> queue = new LinkedList<>();
//新建一个集合
ArrayList<Integer> arrayList = new ArrayList<>();
//将根节点压入到对了中
queue.offer(root);
arrayList.add(root.value);
list.add(arrayList);
while(!queue.isEmpty()){
arrayList = new ArrayList<>();
root = queue.poll();//从队列中跳出根节点
//判断它的左右子节点是否为空,如果不为空,就添加到队列中
if(root.left != null){
queue.offer(root.left);
arrayList.add(root.left.value);
}
if(root.right != null){
queue.offer(root.right);
arrayList.add(root.right.value);
}
list.add(arrayList);
}
}
否则对应的错误结果是这样的:
也正如此,所以需要通过循环嵌套实现二叉树的层序遍历,并且需要直到每一层的节点个数。