1. 先序遍历
1.1 思路
- ①创建一个栈
- ②将根节点入栈
- ③取出栈顶元素并访问
- ④将其右子树入栈,左子树入栈
- ⑤回到③重复
1.2 代码
//这里先序遍历创建一个栈,根->右->左
public static void preOrder(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode> stack=new Stack<>();
stack.push(root);
//栈为空时,对栈pop,会抛出异常,所以要进行判断
while(!stack.isEmpty()){
TreeNode cur=stack.pop();
System.out.print(cur.val+" ");
if(cur.right!=null){
stack.push(cur.right);
}
if(cur.left!=null){
stack.push(cur.left);
}
}
}
2. 中序遍历
2.1 思路
- ①创建一个栈
- ②创建一个引用cur,从根节点出发
- ③cur一路向左,遇到非空的入栈,遇到空时,循环结束
- ④取出栈顶元素并访问
- ⑤让cur指向该节点的右子树,回到③继续执行
2.2 代码
public static void inOrder(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode> stack=new Stack<>();
TreeNode cur=root;
stack.push(cur);
while(true){
while(cur.left!=null){
cur=cur.left;
stack.push(cur);
}
//循环结束,栈非空,取出栈顶元素访问
// 并且让cur指向这个节点的右子树
if(!stack.isEmpty()){
TreeNode node=stack.pop();
System.out.print(node.val+" ");
if(node.right!=null){
stack.push(node.right);
cur=node.right;
}
}else{
break;
}
}
}
3. 后序遍历
3.1 思路
- ①创建一个栈
- ②创建一个引用cur,从根节点出发
- ③cur一路向左,遇到非空入栈,遇到空,首先做出以下两种判断,来判断栈顶元素能否被直接访问:
- I 栈顶元素的右子树是否为空(因为后序遍历时,若右子树为空时,才能直接访问根节点)
- II 栈顶元素的右子树是否被访问过(后序遍历的顺序: 左->右->根,右子树访问过了才能访问根节点)
- ③上面两种情况都不满足,让cur指向栈顶元素的右子树并将其入栈,重复执行③
3.2 代码
public static void postOrder(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode> stack=new Stack<>();
stack.push(root);
TreeNode cur=root;
//prev记录上一个出栈的节点
TreeNode prev=null;
while(true){
while(cur.left!=null){
cur=cur.left;
stack.push(cur);
}
if(!stack.isEmpty()){
TreeNode node=stack.peek();
if(node.right==null||node.right==prev){
prev=node;
System.out.print(node.val+" ");
stack.pop();
}else{
stack.push(node.right);
cur=node.right;
}
}else{
break;
}
}
}