二叉树的四种遍历方式为:前序遍历、中序遍历、后序遍历、层序遍历。这四种遍历方式是所有二叉树都具有的,而不是针对某一种特殊的二叉树。
如果针对二叉搜索树的来看,其中的中序遍历是有特点的:遍历的结果要么是升序、要么是降序,这需要根据我们所实现的具体的比较逻辑来看,总之,二叉搜索树的中序遍历是有序的。
这四种遍历方式中,层序遍历的应用有:可以计算二叉树的高度(当然,递归的方式也是可以实现的);可以判断一个二叉树是否为完全二叉树。
二叉树的前序遍历,可以用于树状结构的展示。比如,我们可以利用前序遍历,来实现打印二叉树的简单效果。
下面代码简单实现了四种遍历:前、中、后序采用递归,层序采用队列实现,遍历到节点后,要做的事写死在了方法内,就是打印。
public class BinaryTree<E> {
private static class Node<E> {
E element;
Node<E> left;
Node<E> right;
public Node(E element) {
this.element = element;
}
}
private Node<E> root;
/*
* 递归实现前序遍历,逻辑写死——打印
* */
public void preorderTraversal() {
preorderTraversal(root);
}
public void preorderTraversal(Node<E> node) {
if (node ==null) return;
System.out.println(node.element);
preorderTraversal(node.left);
preorderTraversal(node.right);
}
/*
* 递归实现中序遍历,逻辑写死——打印
* */
public void inorderTraversal() {
inorderTraversal(root);
}
public void inorderTraversal(Node<E> node) {
if (node == null) return;
inorderTraversal(node.left);
System.out.println(node.element);
inorderTraversal(node.right);
}
/*
* 递归实现后序遍历,逻辑写死——打印
* */
public void postorderTraversal() {
postorderTraversal(root);
}
public void postorderTraversal(Node<E> node) {
if (node == null) return;
postorderTraversal(node.left);
postorderTraversal(node.right);
System.out.println(node.element);
}
/*
* 递归实现层序遍历,逻辑写死——打印
* */
public void levelOrderTraversal() {
if (root == null) return;
Queue<Node<E>> queue = new LinkedList<>();
//代码能执行到这里,说明root不为空,将root入队
queue.offer(root);
while(!queue.isEmpty()) {
Node<E> node = queue.poll();
System.out.println(node.element);
//队列非空,就获取队头节点即出队操作,并判断其左右子节点是否为空
if (node.left != null) {
//左子节点非空,就入队
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
}
如果遍历到节点之后,想做的操作不是打印,就不能将其写死在方法内部,而应提供一个接口,具体想做什么,在实现的时候完成即可。
//为了访问时候,不将逻辑写死,实现的时候再具体写,定义一个遍历接口
public static interface Visitor<E> {
void visit(E element);
}
public void levelOrder(Visitor<E> visitor) {
if (root == null) return;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
Node<E> node = queue.poll();
//System.out.println(node.element);
visitor.visit(node.element);//真正的逻辑在用的时候具体实现
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
//递归前序,具体逻辑具体实现
public void preorder(Visitor<E> visitor) {
preorder(root,visitor);
}
public void preorder(Node<E> node, Visitor<E> visitor) {
if (node== null || visitor == null) return;
visitor.visit(node.element);
preorder(node.left, visitor);
preorder(node.right, visitor);
}
//递归中序,具体逻辑具体实现
public void inorder(Visitor<E> visitor) {
inorder(root,visitor);
}
public void inorder(Node<E> node, Visitor<E> visitor) {
if (node== null || visitor == null) return;
inorder(node.left, visitor);
visitor.visit(node.element);
inorder(node.right, visitor);
}
//递归后序,具体逻辑具体实现
public void postorder(Visitor<E> visitor) {
postorder(root,visitor);
}
public void postorder(Node<E> node, Visitor<E> visitor) {
if (node== null || visitor == null) return;
postorder(node.left, visitor);
postorder(node.right, visitor);
visitor.visit(node.element);
}