前序遍历
如果要实现二叉的在非递归遍历需要借助栈
这个数据结构。因为前序遍历先处理的是根节点再处理左子树和右子树,所以在循环之前需要将根棵树的根节点放入栈中,在循环中,将根元素的值出栈将其中的值加入至存储遍历结果的列表中,再判断左中节点是否存在,如果存在就将其入栈,直至栈空为止。
在子树节点入栈时,先将右子树的根节点入栈,再将左子树的根节点入栈。因为栈是后进先出,二叉树遍历先处理左子树再处理右子树,对应到栈这个数据结构中,先将右子树入栈再将左子树入栈,出栈时就将先将左子树的根节点出栈,先处理的也就是左子树。
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
if (root == null) return null;
Stack<Integer> stack = new Stack<>();
List<Integer> result = new ArrayList<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode pop = stack.pop();
result.add(pop.val);
if (root.right == null) {
stack.push(root.right);
}
if (root.left == null) {
stack.push(root.left);
}
}
return result;
}
}
后序遍历
后序遍历只需要在前序遍历基础将左右子树的根节点入栈顺序交换一下即可。
后序遍历二叉树处理的遍历是 左-->右-->中,
我们在交换了遍历顺序换的处理顺序是 中-->右-->左
两种遍历处理结点的顺序是互逆的,非递归处理完二叉树后,将结果集进行逆置操作返回。
public class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) return null;
Stack<Integer> stack = new Stack<Integer>();
List<Integer> result = new ArrayList<Integer>()j;
stack.psuh(root);
while(!stack.isEmpty()) {
TreeNode pop = stack.pop();
result.add(pop.val);
if (root.left != null) {
stack.push(root.left);
}
if (root.right != null) {
stack.push(root.right);
}
}
return Collections.reverse(result);
}
}
中序遍历
在处理中序遍历时,不像前序和中序遍历那样需要有单特的算法思路。
中序是先处理顺序是 左-->中-->右
从树根节点在开操作,先访问根节点,因为我们要先处理左结点需要,先将根节点在栈中保存下来,当处理到最左叶子节点时,将其中的元素放到结果集当中,出栈再弹出根节点,处理完根节点后,再处理右节点,以此类推即可。
public class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) return null;
Stack<Integer> stack = new Stack<>();
List<Integer> result = new ArrayList<>();
stack.push(root);
TreeNode current = root;
while (!stack.isEmpty() || current != null) {
if (current != null) {
stack.push(current);
current = current.left;
} else {
current= stack.pop();
result.add(current.val);
current = current.right;
}
}
return result;
}
}
循环条件 !stack.isEmpty()代表还有元素要处理,当处理完根元素时,stack.isEmpty()是空,但是还要右子树没有处理,我们还要加上current != null,并且以或关系运算。
在处理元素时,current != null代表还没有处理要根节点,需要将节点信息保存到栈中,因为先处理左子树所以current赋为左子树的值根节点的值,在current为空后,代表处理到了叶子节点,需要将值保存到结查集当中,再去处理右节点。