写法一(各个步骤分离)
前序遍历
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
//迭代算法
preorderStack(root, list);
return list;
}
//通过栈的先进后出特性,将root节点放到栈中,对二叉树从遍历
public void preorderStack(TreeNode root, List<Integer> list){
Deque<TreeNode> stack = new LinkedList<>();
while(root != null || stack.isEmpty()){
//root不为null时,将root节点和左子树节点放到栈中
while(root != null){
//获取根节点数据
list.add(root.val);
//将root节点放入栈中
stack.push(root);
//处理root左子树节点
root = root.left;
}
//root为null,获取栈中root节点
root = stack.pop();
//处理root右子树节点
root = root.right;
}
}
}
中序遍历
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
//迭代算法
inorderStack(root, list);
return list;
}
//通过栈的先进后出特性,将root节点放到栈中,对二叉树从遍历
public void inorderStack(TreeNode root, List<Integer> list){
//定义一个栈用于存放二叉树
Deque<TreeNode> stack = new LinkedList<>();
while(root != null || stack.isEmpty()){
//root不为null时,将root节点和左子树节点放到栈中
while(root != null){
//将root节点放入栈中
stack.push(root);
//处理root左子树节点
root = root.left;
}
//root为null,获取栈中root节点
root = stack.pop();
//获取根节点数据
list.add(root.val);
//处理root右子树节点
root = root.right;
}
}
}
后序遍历
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
//迭代算法
postorderStack(root, list);
return list;
}
//通过栈的先进后出特性,将root节点放到栈中,对二叉树从遍历
public void postorderStack(TreeNode root, List<Integer> list){
//定义一个栈用于存放二叉树
Deque<TreeNode> stack = new LinkedList<>();
//用于判断当前处理右子树与上次处理的二叉树是否相同,避免再处理一次
TreeNode pre = null;
while(root != null || stack.isEmpty()){
//root不为null时,将root节点和左子树节点放到栈中
while(root != null){
//将root节点放入栈中
stack.push(root);
//处理root左子树节点
root = root.left;
}
//root为null,获取栈中root节点
root = stack.pop();
//右子树为null 或 右子树 与 上次处理的pre 子树相等 不需在处理一遍, 取root节点值
if(root.right == null || root.right == pre){
//获取根节点数据
list.add(root.val);
//将当前root节点赋值给pre 用于标记
pre = root;
//将root重置为null,再次出栈遍历处理
root = null;
}else{
//右子树不为null时,需将右子树入栈处理
stack.push(root);
//处理root右子树节点
root = root.right;
}
}
}
}
写法二
// 前序遍历顺序:中-左-右,入栈顺序:中-右-左
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null){
return result;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.right != null){
stack.push(node.right);
}
if (node.left != null){
stack.push(node.left);
}
}
return result;
}
}
// 中序遍历顺序: 左-中-右 入栈顺序: 左-右
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null){
return result;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()){
if (cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
}
// 后序遍历顺序 左-右-中 入栈顺序:中-左-右 出栈顺序:中-右-左, 最后翻转结果
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null){
return result;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.left != null){
stack.push(node.left);
}
if (node.right != null){
stack.push(node.right);
}
}
Collections.reverse(result);
return result;
}
}
写法三(三种遍历统一格式)
迭代法前序遍历代码如下:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new LinkedList<>();
Stack<TreeNode> st = new Stack<>();
if (root != null) st.push(root);
while (!st.empty()) {
TreeNode node = st.peek();
if (node != null) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右左中节点添加到栈中(前序遍历-中左右,入栈顺序右左中)
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
st.push(node); // 添加中节点
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.peek(); // 重新取出栈中元素
st.pop();
result.add(node.val); // 加入到结果集
}
}
return result;
}
}
迭代法中序遍历代码如下:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new LinkedList<>();
Stack<TreeNode> st = new Stack<>();
if (root != null) st.push(root);
while (!st.empty()) {
TreeNode node = st.peek();
if (node != null) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中(中序遍历-左中右,入栈顺序右中左)
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
st.push(node); // 添加中节点
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.peek(); // 重新取出栈中元素
st.pop();
result.add(node.val); // 加入到结果集
}
}
return result;
}
}
迭代法后序遍历代码如下:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new LinkedList<>();
Stack<TreeNode> st = new Stack<>();
if (root != null) st.push(root);
while (!st.empty()) {
TreeNode node = st.peek();
if (node != null) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将中右左节点添加到栈中(后序遍历-左右中,入栈顺序中右左)
st.push(node); // 添加中节点
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.peek(); // 重新取出栈中元素
st.pop();
result.add(node.val); // 加入到结果集
}
}
return result;
}
}