力扣-树-非递归遍历
1.前序遍历(LeetCode 144)
——中、左、右
- 解题思路:先找到最左下角结点,将节点压入堆栈,同时将节点加入遍历集中,这样就完成了中、左的顺序。知道找到最左下角后,pop栈顶在找其右结点即可,即完成了中、左、右的顺序。
- (这个地方最好还是多拿几个例子试试,才能明白)
class Solution1 {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
//找到最左下角的结点
while (node != null) {
res.add(node.val);
stack.push(node);
node = node.left;
}
node = stack.pop();
node = node.right;
}
return res;
}
}
2.中序遍历(LeetCode 94)
——左、中、右
- 解题思路:中序和前序的大体思路相同,只是在插入res集合的位置不同,要先找到左下角的结点后,先将左下角结点入栈
class Solution1 {
public List<Integer> inorderTraversal(TreeNode root) {
Deque<TreeNode> stack=new LinkedList<>();
List<Integer> res=new ArrayList<>();
if(root==null) return res;
while(!stack.isEmpty()||root!=null){
while(root!=null){
stack.push(root);
root=root.left;
}
root=stack.pop();
res.add(root.val);
root=root.right;
}
return res;
}
}
3.后序遍历(LeetCode 145)
——左、右、中
- 解题思路:后序遍历相比前、中序较为麻烦,也是先找到最左下角的结点,这里注意有一点不同的是在找其右结点的时候要分类讨论,详细见代码中的备注,写的比较清楚了(还是要多找几个例子自己试一下)
class Solution1 {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode prev = null;
while (root != null || !stack.isEmpty()) {
//找到最左下角结点
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
//root==right是为了遍历右结点,root.tight==prev是为了能从深往浅返回去(已经遍历完左右结点回到该结点时)
if (root.right == null || root.right == prev) {
res.add(root.val);
prev = root;
//root=null为了防止进入上面的循环
root = null;
}
//如果有右节点就要将目前的结点压回栈,因为按照后序遍历的顺序,该节点要在右结点后被遍历
else {
stack.push(root);
root = root.right;
}
}
return res;
}
}