二叉树的多种遍历——Java

二叉树遍历详解
本文详细介绍了二叉树的六种遍历方法:先序、中序、后序、层次、深度优先及广度优先遍历,并通过具体示例展示了每种遍历方式的应用效果。
package research;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * 二叉树的多种遍历:先序遍历、中序遍历、后序遍历、层次遍历、深度优先遍历、广度优先遍历
 * 
 * @author Sam
 *
 */
public class BinaryTree {
	public static void main(String[] args) {
		Node root = Factory.create(4);
		System.out.print("先序遍历:");
		NLR(root);
		System.out.println();
		System.out.print("中序遍历:");
		LNR(root);
		System.out.println();
		System.out.print("后序遍历:");
		LRN(root);
		System.out.println();
		System.out.print("层次遍历:");
		Level(root);
		System.out.println();
		System.out.print("深度优先遍历:");
		depthFirstSearch(root);
		System.out.println();
		System.out.print("广度优先遍历:");
		breadthFirstSearch(root);
	}

	/**
	 * 先序遍历:首先访问根,再先序遍历左(右)子树,最后先序遍历右(左)子树。
	 * 
	 * @param n
	 */
	static void NLR(Node n) {
		if (null == n) {
			return;
		}
		System.out.print(n);
		NLR(n.getLeft());
		NLR(n.getRight());
	}

	/**
	 * 中序遍历:首先中序遍历左(右)子树,再访问根,最后中序遍历右(左)子树。
	 * 
	 * @param n
	 */
	static void LNR(Node n) {
		if (null == n) {
			return;
		}
		LNR(n.getLeft());
		System.out.print(n);
		LNR(n.getRight());
	}

	/**
	 * 后序遍历:首先后序遍历左(右)子树,再后序遍历右(左)子树,最后访问根。
	 * 
	 * @param n
	 */
	static void LRN(Node n) {
		if (null == n) {
			return;
		}
		LRN(n.getLeft());
		LRN(n.getRight());
		System.out.print(n);

	}

	/**
	 * 层次遍历:即按照层次访问,通常用队列来做。访问根,访问子女,再访问子女的子女(越往后的层次越低)(两个子女的级别相同).
	 * Queue1与Queue2交互存储二叉树的每一层
	 * 
	 * @param n
	 */
	static void Level(Node n) {
		Queue<Node> queue1 = new LinkedList<Node>();
		Queue<Node> queue2 = new LinkedList<Node>();
		queue1.add(n);
		while (!queue1.isEmpty() || !queue2.isEmpty()) {
			System.out.println();
			while (!queue1.isEmpty()) {
				Node curNode = queue1.poll();
				System.out.print(curNode);
				if (null != curNode.getLeft()) {
					queue2.add(curNode.getLeft());
				}
				if (null != curNode.getRight()) {
					queue2.add(curNode.getRight());
				}
			}
			System.out.println();
			while (!queue2.isEmpty()) {
				Node curNode = queue2.poll();
				System.out.print(curNode);
				if (null != curNode.getLeft()) {
					queue1.add(curNode.getLeft());
				}
				if (null != curNode.getRight()) {
					queue1.add(curNode.getRight());
				}
			}
		}
	}

	/**
	 * 深度优先遍历
	 * 
	 * @param root
	 */
	static void depthFirstSearch(Node root) {
		Stack<Node> stack = new Stack<Node>();
		stack.push(root);
		Node node;
		while (!stack.empty()) {
			node = stack.pop();
			System.out.print(node);
			if (null != node.getRight()) {
				stack.push(node.getRight());// 先将右子树压栈
			}
			if (null != node.getLeft()) {
				stack.push(node.getLeft());// 再将左子树压栈
			}
		}
	}

	/**
	 * 广度优先遍历
	 * 
	 * @param root
	 */
	static void breadthFirstSearch(Node root) {
		Queue<Node> queue = new LinkedList<Node>();
		queue.add(root);
		Node node;
		while (!queue.isEmpty()) {
			node = queue.poll();
			System.out.print(node);
			if (null != node.getLeft()) {
				queue.add(node.getLeft());// 先将左子树入队
			}
			if (null != node.getRight()) {
				queue.add(node.getRight());// 再将右子树入队
			}
		}
	}

}

class Node {
	private Object data;
	private Node left;
	private Node right;

	public Node() {

	}

	public Node(Object o) {
		data = o;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

	public Node getLeft() {
		return left;
	}

	public void setLeft(Node left) {
		this.left = left;
	}

	public Node getRight() {
		return right;
	}

	public void setRight(Node right) {
		this.right = right;
	}

	@Override
	public String toString() {
		return null == data ? "" : String.format(" %s ", data.toString());
	}
}

/**
 * (1)空二叉树<br>
 * (2)只有一个根结点的二叉树<br>
 * (3)只有左子树<br>
 * (4)只有右子树<br>
 * (5)完全二叉树。
 * 
 * @author Sam
 *
 */
class Factory {
	public static Node create(int deep) {
		return create(1, 1, deep);
	}

	private static Node create(int data, int h, int deep) {
		Node parent = new Node(data);
		if (h < deep) {
			int next = h + 1;
			parent.setLeft(create(data * 2, next, deep));
			parent.setRight(create(data * 2 + 1, next, deep));
		}

		return parent;
	}
}

运行结果:

先序遍历: 1  2  4  8  9  5  10  11  3  6  12  13  7  14  15 
中序遍历: 8  4  9  2  10  5  11  1  12  6  13  3  14  7  15 
后序遍历: 8  9  4  10  11  5  2  12  13  6  14  15  7  3  1 
层次遍历:
 1 
 2  3 
 4  5  6  7 
 8  9  10  11  12  13  14  15 
深度优先遍历: 1  2  4  8  9  5  10  11  3  6  12  13  7  14  15 
广度优先遍历: 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 


### Java 二叉树遍历实现方法 #### 定义二叉树的节点类 为了在Java中操作二叉树,首先需要定义一个表示二叉树节点的类。这个类通常包含三个主要部分:存储数据的变量、指向左子节点的引用以及指向右子节点的引用。 ```java class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } ``` #### 构建二叉树 创建具体的二叉树实例可以通过设置各个`TreeNode`对象之间的连接来完成。这一步骤可以根据实际需求灵活调整,比如通过数组输入或其他形式的数据源动态建立一棵完整的二叉树结构[^1]。 #### 遍历方式介绍 对于给定的一棵二叉树来说,存在多种不同的遍历策略用于访问其所有的节点: - **前序遍历**(先根遍历):按照“根->左->右”的顺序依次访问各节点; - **中序遍历**:遵循“左->根->右”的路径进行访问; - **后序遍历**:采取“左->右->根”的模式遍历整个树形结构; - **层次遍历**:从上到下逐层扫描每一行上的所有元素[^4]。 这里重点展示如何利用递归来实现上述三种常见的深度优先搜索(DFS)类型的遍历算法——即前序、中序和后序遍历。 ##### 前序遍历代码示例 当执行前序遍历时,会先处理当前节点再分别对其左右两个分支做相同的操作直到遇到叶子为止。 ```java public static void preOrder(TreeNode node){ if(node != null){ System.out.print(node.val+" "); preOrder(node.left); preOrder(node.right); } } ``` ##### 中序遍历代码示例 中序遍历则是在访问完左侧之后才打印出当前节点的信息并继续探索右侧的部分。 ```java public static void inOrder(TreeNode node){ if(node!=null){ inOrder(node.left); System.out.print(node.val+" "); inOrder(node.right); } } ``` ##### 后序遍历代码示例 而后序遍历则是等到左右两侧都被完全解析过后才会输出该位置处的内容。 ```java public static void postOrder(TreeNode node){ if(node!=null){ postOrder(node.left); postOrder(node.right); System.out.print(node.val+" "); } } ``` 以上就是基于递归机制下的基本二叉树遍历方法,在实际应用当中还可以考虑采用迭代的方式或是借助栈这种辅助性的数据结构来进行优化改进[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值