二叉树的层级遍历/锯齿遍历--Java版

本文介绍了如何使用Java实现二叉树的层级遍历和锯齿形层次遍历。通过创建节点对象、树对象,利用队列进行层次遍历,并在层级遍历的基础上调整节点输出顺序以实现锯齿遍历。文中提供了详细的解题思路、代码示例及测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

  • 今天在力扣上看到这样一道题,感觉挺有趣,而后几经挫折解出来,结果和其他博主的有异同~

题目

  • 给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
    例如:给定二叉树: [3,9,20,null,null,15,7]
    给定二叉树
  • 输出
    输出结果
  • 摘自力扣102题

解题思路/知识点

  • 层级遍历二叉树,一般借助队列作为缓冲。
  • 头节点出队列,同时判断头节点是否含有左右子节点,如果有,则入队列。
  • 如何判断层级?
    本篇借助在队列里插入【干扰因子】的方式,即一个标识符来判断层级。
  • 以此树来演示
    在这里插入图片描述
  • 步骤:null入队–>头节点入队(3)–>null出队->null入队尾->头节点出队(3)->头节点的左右节点入队(9/20)->null出队->null入队尾->9出队->20出队;
  • 以上方法表示两个null之间是一个层级,如果还有模糊,不急,showCode。

showCode

  • 万物皆对象~

创建节点对象

public class TreeNode {
	int value;
	TreeNode lNode;
	TreeNode rNode;
	//设置value值
	public void setValue(int value) {
		this.value = value;
	}
	//设置左节点
	public void setlNode(TreeNode lNode){
		this.lNode = lNode;
	}
	//设置右节点
	public void setrNode(TreeNode rNode){
		this.rNode = rNode;
	}
	//前序遍历
	public void frontShow() {
	//先遍历当前节点的内容
	System.out.println(value);
	//遍历左节点
	if(lNode!=null){
		lNode.frontShow();
	}
	//遍历右节点
	if(rNode!=null){
		rNode.frontShow();
		}
	}
		}

创建树对象

public class BinaryTree {
	TreeNode root;
	//设置根节点
	public void setRoot(TreeNode root) {
		this.root = root;
	}
	//前序遍历
	public void frontShow(){
		this.root.frontShow();
	}
}

创建测试类

public class Solution {
	//用于创建二叉树节点集合
	List<TreeNode> treeNodes = new ArrayList<TreeNode>();
	//二叉树
	BinaryTree tree = new BinaryTree();
	
	public static void main(String[] args) {
		
	}
}
  • 首先编写一个创建二叉树的方法,我们使用递归。
	/**
	 * @param index 当前索引
	 * @param node 当前节点
	 * */
public void createBinaryTree(int index,TreeNode node) {
		if(index == 0) {
			tree.setRoot(treeNodes.get(index));
		}
		if(2*index+1<treeNodes.size() && node != null) {
			node.setlNode(treeNodes.get(2*index+1));
			createBinaryTree(2*index+1,node.lNode);
		}
		if(2*index+2<treeNodes.size() && node != null) {
			node.setrNode(treeNodes.get(2*index+2));
			createBinaryTree(2*index+2,node.rNode);
		}
	}
  • 编写前序遍历方法(直接调用节点类方法)测试树是否可以正常创建
public static void main(String[] args) {
		//前序数组
		int[] testTree = {3,9,20,0,0,15,7};
		Solution testSolution = new Solution();
		//创建节点集合
		testSolution.createNodes(testTree);
		TreeNode root = new TreeNode();
		root.value = 3;
		//创建二叉树
		testSolution.createBinaryTree(0, root);
		testSolution.setRoot(root);
		//前序遍历
		testSolution.fontShow();
	}
  • 前序遍历结果
    二叉树的前序遍历结果
  • 此过程设计顺序存储二叉树的知识,将数组—>二叉树

层序遍历

//按照层级遍历二叉树
public void traversal(){
		//使用到的工具集合---队列
		Queue<TreeNode> queue = new LinkedList<TreeNode>();
		//定义结果集
		List<List<Integer>> result = new ArrayList<List<Integer>>();
		//结果集中的List
		List<Integer> res = null;
		queue.add(null);
		queue.add(testSolution.tree.root);
		int level = -1;
		while(!queue.isEmpty()) {
			TreeNode temp=queue.poll();
			//判断层级/防止进入恶性循环
			if(temp == null) {
				level++;
				res = new ArrayList<Integer>();
				result.add(res);
				queue.add(null);
			}
			//防止空指针
			if(res != null && temp != null) {
				result.get(level).add(temp.value);
			}
			if(temp != null && temp.lNode != null && temp.lNode.value != 0) {
				queue.add(temp.lNode);
			}
			if(temp != null && temp.rNode != null && temp.rNode.value != 0) {
				queue.add(temp.rNode);
			}
			if(queue.peek() == null && queue.size()==1) {
				break;
			}
			
		}
		System.out.println("--------------------------------");
		System.out.println(result);
}
  • 上述代码大概是这样一个过程。
    层序遍历二叉树
    -结果输出
    层序遍历结果

锯齿遍历

题目

-给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

例如:
给定二叉树: [3,9,20,null,null,15,7],
在这里插入图片描述
返回其层次遍历结果:

[ [3], [20,9], [15,7] ]

解体思路

  • 有了上面的层序遍历,此题目算是上面的变体,我们只需把层级为偶数的节点值反转以下便可。
//判断层级+1
				if(level!= - 1 && (level+1) % 2 == 0) {
					Collections.reverse(result.get(level));
				}
  • 上述代码大概是这个酱紫
    锯齿遍历二叉树
  • 输出结果
    在这里插入图片描述

源码(测试类)

public class Solution {
	List<TreeNode> treeNodes = new ArrayList<TreeNode>();
	BinaryTree tree = new BinaryTree();
	public static void main(String[] args) {
		//前序数组
		int[] testTree = {3,9,20,0,0,15,7};
		Solution testSolution = new Solution();
		testSolution.createNodes(testTree);
		TreeNode root = new TreeNode();
		root.value = 3;
		testSolution.createBinaryTree(0, root);
		testSolution.setRoot(root);
		//前序遍历
		testSolution.fontShow();
		//按照层级遍历二叉树
		Queue<TreeNode> queue = new LinkedList<TreeNode>();
		//定义结果集
		List<List<Integer>> result = new ArrayList<List<Integer>>();
		//结果集中的List
		List<Integer> res = null;
		queue.add(null);
		queue.add(testSolution.tree.root);
		int level = -1;
		while(!queue.isEmpty()) {
			TreeNode temp=queue.poll();
			//判断层级/防止进入恶性循环
			if(temp == null) {
				//判断层级+1
				//如果是层级,去掉这个if
				if(level!= - 1 && (level+1) % 2 == 0) {
					Collections.reverse(result.get(level));
				}
				level++;
				res = new ArrayList<Integer>();
				result.add(res);
				queue.add(null);
			}
			//防止空指针
			if(res != null && temp != null) {
				result.get(level).add(temp.value);
			}
			if(temp != null && temp.lNode != null && temp.lNode.value != 0) {
				queue.add(temp.lNode);
			}
			if(temp != null && temp.rNode != null && temp.rNode.value != 0) {
				queue.add(temp.rNode);
			}
			if(queue.peek() == null && queue.size()==1) {
				break;
			}
			
		}
		System.out.println(level);
		System.out.println("--------------------------------");
		System.out.println(result);
	}
	//创建节点对象集合,使用ArrayList存
	public void createNodes(int[] tree) {
			for(int i=0;i<tree.length;i++) {
				TreeNode node = new TreeNode();
				node.value = tree[i];
				treeNodes.add(node);
			}
	}
	//创建二叉树(递归)
	/**
	 * @param index 当前索引
	 * @param node 当前节点
	 * */
	public void createBinaryTree(int index,TreeNode node) {
		if(index == 0) {
			tree.setRoot(treeNodes.get(index));
		}
		if(2*index+1<treeNodes.size() && node != null) {
			node.setlNode(treeNodes.get(2*index+1));
			createBinaryTree(2*index+1,node.lNode);
		}
		if(2*index+2<treeNodes.size() && node != null) {
			node.setrNode(treeNodes.get(2*index+2));
			createBinaryTree(2*index+2,node.rNode);
		}
	}
	//前序遍历
	public void fontShow() {
		tree.frontShow();
	}
	//设置根节点对象
	public void setRoot(TreeNode node) {
		tree.setRoot(node);
	}
}

结语

如有错误,欢迎指正~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值