这里总结了非递归的不同解法
中序遍历 非递归
//中序遍历 非递归
void inorderTraservel(TreeNode root){
TreeNode p = root;
Deque<TreeNode> stack = new LinkedList<>();
while(p != null || !stack.isEmpty()){
while(p != null){
stack.push(p);
p = p.left;
}
p = stack.pop();
System.out.println(p.val);
p = p.right;
}
}
先序遍历 非递归
//先序遍历 非递归
//思路1,根据中序遍历改造,在将节点入栈的同时,输出它;然后再去遍历左节点;最后遍历右节点
void preorderTraservel_1(TreeNode root){
TreeNode p = root;
Deque<TreeNode> stack = new LinkedList<>();
while(p != null || !stack.isEmpty()){
while(p != null){
stack.push(p);
System.out.println(p.val);
p = p.left;
}
p = stack.pop();
p = p.right;
}
}
//思路2,先遍历父节点,然后将所有子节点入栈,再从栈中去一个节点,将这个节点的子节点入栈,这样往复直至栈为空(和深度优先遍历的思想一致)
void preorderTraservel_2(TreeNode root){
TreeNode p = root;
Deque<TreeNode> stack = new LinkedList<>();
stack.push(p);
while(!stack.isEmpty()){
p = stack.pop();
System.out.println(p.val);
while(p.right != null) stack.push(p);
while(p.left != null) stack.push(p);
}
}
后序遍历 非递归
//后序遍历 非递归
//思路1,也是按照中序遍历那样入栈,先遍历左节点,然后取栈顶不弹出,查看它是否有右子节点或者右子节点是否被遍历过,没有遍历过指针指向右节点;遍历过,输出父节点
void postorderTraservel_1(TreeNode root){
TreeNode p = root, pre = null;
Deque<TreeNode> stack = new LinkedList<>();
while(p != null || !stack.isEmpty()){
while(p != null){
stack.push(p);
p = p.left;
}
p = stack.peek();
if(p.right != null && p.right != pre){
p = p.right;
}else{
stack.pop();
System.out.println(p.val);
pre = p;//更新上一节点
p = null;//这里要将p置为空,否则p的左子树又会入栈
}
}
}
//思路2,先序遍历的结果翻转过来就是后序遍历
void postorderTraservel_2(TreeNode root){
TreeNode p = root;
Deque<TreeNode> stack = new LinkedList<>();
Deque<int> result_stack = new LinkedList<>();
stack.push(p);
while(!stack.isEmpty()){
p = stack.pop();
System.out.println(p.val);
result_stack.push(p.val);//输出的同时把结果入栈,最终后序遍历的结果就是依次出栈的结果
while(p.right != null) stack.push(p);
while(p.left != null) stack.push(p);
}
}