二叉树的遍历
1 前序遍历
二叉树的前序遍历顺序为:根->左->右
递归代码如下:
/**
* 二叉树前序遍历递归
* @param root
*/
public void preorderTraverse(TreeNode root) {
if (root == null)
return;
System.out.println(root.val);
// 遍历左子树
preorderTraverse(root.left);
// 遍历右子树
preorderTraverse(root.right);
}
非递归算法利用了栈来实现。
/**
* 二叉树前序遍历非递归
* @param root
*/
public void preorderTraverseWithStack(TreeNode root) {
if (root == null)
return;
TreeNode cur = root;
Stack<TreeNode> stack = new Stack<>();
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
System.out.println(cur.val);
cur = cur.left;
}
TreeNode node = stack.pop();
cur = node.right;
}
}
前序遍历是是一直遍历左子树,遍历一个结点就输出一个结点,然后再将结点入栈。遍历到最左边结点后,开始出栈。输出栈顶元素。并且需要判断栈顶元素是否有右子树,如果有,继续先序遍历右子树
2 中序遍历
二叉树的前序遍历顺序为:左->根->右
递归代码如下:
/**
* 二叉树中序遍历递归
* @param root
*/
public void inorderTraverse(TreeNode root) {
if (root == null)
return;
inorderTraverse(root.left);
System.out.println(root.val);
inorderTraverse(root.right);
}
非递归代码如下:
/**
* 二叉树中序遍历非递归
* @param root
*/
public void inorderTraverseWithStack(TreeNode root) {
if (root == null)
return;
TreeNode cur = root;
Stack<TreeNode> stack = new Stack<>();
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode pop = stack.pop();
System.out.println(pop.val);
cur = cur.right;
}
}
这里需要对比前序遍历的代码。中序遍历是一直沿着左子树深入,然后没遍历一个结点,就将该结点入栈,先不打印。等遍历到最左边结点后,开始出栈,并打印栈顶元素。然后判断栈顶元素是否有右子树,如果有,则继续遍历右子树。
3 后序遍历
二叉树的前序遍历顺序为:左->右->根
递归代码如下:
/**
* 二叉树后序遍历递归
* @param root
*/
public void poseOrderTraverse(TreeNode root) {
if (root == null)
return;
poseOrderTraverse(root.left);
poseOrderTraverse(root.right);
System.out.println(root.val);
}
非递归代码如下:
/**
* 二叉树后序遍历非递归
* @param root
*/
public void postOrderWithStack(TreeNode root) {
if (root == null)
return;
TreeNode cur = root;
TreeNode pre = null;
Stack<TreeNode> stack = new Stack<>();
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
// 因为左子树已经遍历到不存在左子树到结点了,因此这里是需要判断栈顶元素是否有右子树
// 如果存在右子树,那么先去继续后续遍历右子树 否则直接栈顶元素出栈
cur = stack.peek();
if (cur.right != null || pre == cur.right) {
// 说明栈顶元素不存在右子树或者右子树已经遍历完毕
// 那么可以出栈了
TreeNode pop = stack.pop();
System.out.println(pop.val);
pre = pop;
cur = null;
} else {
// 不满足条件则说明栈顶元素还有右子树,并且右子树没有被遍历,那么先对右子树进行后续遍历
cur = cur.right;
}
}
}
后序遍历也是先沿着左子树深入,每遍历一个结点就入栈。遍历到最左边结点后,开始出栈。出栈之前需要判断栈顶元素是否有右子树或者右子树是否已经遍历完了。如果满足上述条件,则出栈。否则继续遍历右子树。
4 层序遍历
层序遍历就是按照二叉树每一层,从左到右进行遍历。
层序遍历一般采用的都是基于队列的非递归算法。代码如下:
/**
* 二叉树层序遍历
* @param root
*/
public void levelTraverse(TreeNode root) {
if (root == null)
return;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode poll = queue.poll();
System.out.println(poll.val);
if(poll.left != null)
queue.offer(poll.left);
if (poll.right != null)
queue.offer(poll.right);
}
}