二叉树的逐层遍历--java实现

需求一:

    逐层遍历二叉树并输出,每一层占一行。

分析:

思路一:

    1、逐层遍历二叉树也是BFS遍历二叉树,因此数据结构选择队列。
    2、需要用两个变量存储当前层待遍历的节点个数以及下一行的节点个数。
    3、将头结点加入队列尾,当队列不是空的,就移除队列头部元素并输出,并将其儿子节点加入队列尾,当前层待遍历节点个数减一,更新下一层节点个数。
    4、当当前层待遍历节点个数为0时,说明已经遍历了一行,这时就需要换行。

思路二:

    思路一中定义了两个变量,存储当前行待遍历节点个数以及下一层节点个数,我们也可不用这两个变量。因为每次判断队列是否是空的时候,此时队列长度就是当前层的节点个数,记录该值,即为当前层的遍历次数,遍历结束即换行。

需求二:

    逐层遍历二叉树,将每一层的节点值存到集合中,最后返回包含每一层节点值的集合。

分析:

思路一:

    同需求一中的思路一,定义两个变量记录当前层和下一层节点个数。创建一个List集合,用于存储每一层的节点值,当该层遍历结束,将该层List集合添加到结果集合中,然后更新两个变量值,并且清空List集合

思路二:

    同需求一中的思路二,不用定义两个变量。每次判断是否为空的时候,创建List集合,用变量记录此时队列长度,即当前层应该遍历的节点个数,遍历结束意味着已经遍历了当前行,将该List集合添加到结果集合中即可

代码:

import java.util.*;

class BinTree{
	//表示二叉树的字符串数组
	private String[] str;
	//表示二叉树的List集合
	private List list;

	//构造函数
	//传入字符串数组
	BinTree(String[] str){
		this.str = str;
	}

	//二叉树节点内部类
	class Node{
		int val;
		Node left;
		Node right;

		Node(int val){
			this.val = val;

			this.left = null;
			this.right = null;
		}
	}

	//创建二叉树
	public void createBinTree(){
		list = new LinkedList();

		//遍历字符串数组,将字符串转成相应的节点
		for(String s : str){
			//如果s是#,那么对应null
			if("#".equals(s)){
				list.add(null);
			}
			//否则对应有值的节点
			else{
				list.add(new Node(Integer.parseInt(s)));
			}
		}

		//构建二叉树父子节点直接的关系
		for(int index = 0; index < str.length/2-1; index++){
			//如果节点不是null的,需要加上其左右儿子节点
			if(list.get(index) != null){
				list.get(index).left = list.get(index*2+1);
				list.get(index).right = list.get(index*2+2);
			}
		}

		//单独处理最后一个节点
		int lastIndex = str.length/2-1;
		//添加左儿子
		list.get(lastIndex).left = list.get(lastIndex*2+1);

		//如果数组长度是奇数,说明有右儿子
		if(str.length % 2 != 0){
			list.get(lastIndex).right = list.get(lastIndex*2+2);
		}
	}

	//获取二叉树根
	public Node getRoot(){
		if(list != null){
			return list.get(0);
		}

		System.out.println("请先创建二叉树");
		return null;
	}

	//获取二叉树的深度,即最大深度
	public int maxDepth(Node root){
		if(root == null){
			return 0;
		}

		//将深度初始化为1
		int depth = 1;

		//求左儿子的最大深度
		int leftMaxDepth = maxDepth(root.left);
		//求右儿子的最大深度
		int rightMaxDepth = maxDepth(root.right);

		return Math.max(leftMaxDepth, rightMaxDepth)+depth;
	}

	//获取二叉树的最小深度
	public int minDepth(Node root){
		if(root == null){
			return 0;
		}

		//深度初始化为1
		int depth = 1;

		//求左儿子的最小深度
		int leftMinDepth = minDepth(root.left);
		//求右儿子的最小深度
		int rightMinDepth = minDepth(root.right);

		//如果左儿子树或者右儿子树最小深度是0,那么就返回另一个长度
		if(leftMinDepth == 0){
			return rightMinDepth+depth;
		}
		if(rightMinDepth == 0){
			return leftMinDepth+depth;
		}

		return Math.min(leftMinDepth, rightMinDepth)+depth;
	}
}

class LayerTraversal{
	//需求一
	//思路一
	public static void layerPrint1(BinTree.Node root){
		if(root == null){
			throw new IllegalArgumentException("invalid parameters");
		}

		//创建队列,存储二叉树节点
		Queue queue = new ArrayDeque();
		//把根结点加到队列尾
		queue.offer(root);

		//当前层待遍历个数
		int toBeVisit = 1;
		//下一层节点个数
		int nextLevel = 0;

		while(!queue.isEmpty()){
			BinTree.Node temp = queue.poll();//移除头结点
			System.out.print(temp.val+" ");

			//添加移除的节点的左儿子节点
			if(temp.left != null){
				nextLevel++;
				queue.offer(temp.left);
			}
			//添加移除的节点的右儿子节点
			if(temp.right != null){
				nextLevel++;
				queue.offer(temp.right);
			}

			//当前层待遍历节点个数减一
			toBeVisit--;

			//如果=0,代表当前层已经遍历完
			if(toBeVisit == 0){
				System.out.println();//换行

				toBeVisit = nextLevel;
				nextLevel = 0;
			}
		}
	}

	//需求一
	//思路二
	public static void layerPrint2(BinTree.Node root){
		if(root == null){
			throw new IllegalArgumentException("invalid parameters");
		}

		//创建队列,存储二叉树节点
		Queue queue = new ArrayDeque();
		//把根节点存到队列尾
		queue.offer(root);

		//当队列不是空的时候,将队列头移除,将其儿子节点加入队列
		while(!queue.isEmpty()){
			int size = queue.size();//记录当前层节点的个数

			BinTree.Node temp;

			//遍历size次
			for(int i = 0; i < size; i++){
				temp = queue.poll();
				System.out.print(temp.val+" ");

				//添加儿子节点到队列中
				if(temp.left != null){
					queue.offer(temp.left);
				}
				if(temp.right != null){
					queue.offer(temp.right);
				}
			}

			System.out.println();//换行
		}
	}

	//需求二
	//思路一
	public static List> getList1(BinTree.Node root){
		if(root == null){
			throw new IllegalArgumentException("invalid parameters");
		}

		//创建队列,存储二叉树节点
		Queue queue = new ArrayDeque();
		//把根节点存到队列尾
		queue.offer(root);
		
		//当前层待遍历节点个数
		int toBeVisit = 1;
		//下一层节点个数
		int nextLevel = 0;

		//创建结果集合
		List> result = new ArrayList>();

		//创建集合,存储每一行的节点值
		List list = new LinkedList();

		while(!queue.isEmpty()){
			BinTree.Node temp = queue.poll();
			list.add(temp.val);

			if(temp.left != null){
				nextLevel++;
				queue.offer(temp.left);
			}
			if(temp.right != null){
				nextLevel++;
				queue.offer(temp.right);
			}

			//待遍历节点数减一
			toBeVisit--;

			//当待遍历节点数为0,代表当前行已经遍历完
			if(toBeVisit == 0){
				//把当前list集合中的元素存到result中,注意不能直接result.add(list),因为后面要清空list集合,result也会受到影响
				//所以可以创建新的集合,存储list集合元素,然后添加到result中
				List l = new LinkedList();
				l.addAll(list);

				result.add(l);

				toBeVisit = nextLevel;
				nextLevel = 0;
				list.clear();//清空共有的List集合
			}
		}

		return result;
	}

	//需求二
	//思路二
	public static List> getList2(BinTree.Node root){
		if(root == null){
			throw new IllegalArgumentException("invalid parameters");
		}

		//创建结果集合
		List> result = new ArrayList>();

		//创建队列,存储二叉树节点
		Queue queue = new ArrayDeque();
		//把根节添加到队列尾
		queue.offer(root);

		//当队列中不为空
		while(!queue.isEmpty()){
			//创建List集合存储当前层节点值
			List list = new LinkedList();

			//记录当前层的节点个数
			int size = queue.size();
			BinTree.Node temp;

			for(int i = 0; i < size; i++){
				temp = queue.poll();
				list.add(temp.val);

				if(temp.left != null){
					queue.offer(temp.left);
				}
				if(temp.right != null){
					queue.offer(temp.right);
				}
			}

			result.add(list);
		}

		return result;
	}

	public static void main(String[] args){
		String[] str = {
			"1", "2", "3", "4", "#", "#", "7"
		};

		//构建二叉树
		BinTree bt = new BinTree(str);
		bt.createBinTree();
		
		//层次遍历
		System.out.println("逐层打印:");
		layerPrint1(bt.getRoot());

		System.out.println("逐层打印2:");
		layerPrint2(bt.getRoot());

		System.out.println("二叉树分层集合:");
		System.out.println(getList1(bt.getRoot()));
		System.out.println("二叉树分层集合:");
		System.out.println(getList2(bt.getRoot()));
	}
}


你可能感兴趣的:(算法,java,二叉树,遍历)